python3+PyQt5泛型委托詳解
自定義委托可以讓我們對視圖中出現(xiàn)的數(shù)據(jù)項(xiàng)的外觀和行為進(jìn)行完全控制。如果有很多模型,可能會希望不是全部的大多數(shù)模型能夠僅用一個(gè)自定義委托,如果不能這么做,那么對于這些自定義委托,將很有可能存在大量重復(fù)代碼。為了使得維護(hù)工作變得輕松,更好的方法為不要為每個(gè)模型創(chuàng)建一個(gè)自定義委托,而是用一系列的通用組件來共同構(gòu)成一個(gè)委托。本文通過Python3+pyqt5實(shí)現(xiàn)了python Qt GUI 快速編程的16章的泛型委托例子。
/home/yrd/eric_workspace/chap16/richtextlineedit.py
#!/usr/bin/env python3
import platform
import sys
import html
from PyQt5.QtCore import QSize, Qt,pyqtSignal
from PyQt5.QtGui import QColor, QFont,QFontMetrics, QIcon, QKeySequence, QPixmap,QTextCharFormat
from PyQt5.QtWidgets import QAction,QApplication,QMenu,QTextEdit
class RichTextLineEdit(QTextEdit):
returnPressed=pyqtSignal()
(Bold, Italic, Underline, StrikeOut, Monospaced, Sans, Serif,
NoSuperOrSubscript, Subscript, Superscript) = range(10)
def __init__(self, parent=None):
super(RichTextLineEdit, self).__init__(parent)
self.monofamily = "courier"
self.sansfamily = "helvetica"
self.seriffamily = "times"
self.setLineWrapMode(QTextEdit.NoWrap)
self.setTabChangesFocus(True)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
fm = QFontMetrics(self.font())
h = int(fm.height() * (1.4 if platform.system() == "Windows"
else 1.2))
self.setMinimumHeight(h)
self.setMaximumHeight(int(h * 1.2))
self.setToolTip("Press <b>Ctrl+M</b> for the text effects "
"menu and <b>Ctrl+K</b> for the color menu")
def toggleItalic(self):
self.setFontItalic(not self.fontItalic())
def toggleUnderline(self):
self.setFontUnderline(not self.fontUnderline())
def toggleBold(self):
self.setFontWeight(QFont.Normal
if self.fontWeight() > QFont.Normal else QFont.Bold)
def sizeHint(self):
return QSize(self.document().idealWidth() + 5,
self.maximumHeight())
def minimumSizeHint(self):
fm = QFontMetrics(self.font())
return QSize(fm.width("WWWW"), self.minimumHeight())
def contextMenuEvent(self, event):
self.textEffectMenu()
def keyPressEvent(self, event):
if event.modifiers() & Qt.ControlModifier:
handled = False
if event.key() == Qt.Key_B:
self.toggleBold()
handled = True
elif event.key() == Qt.Key_I:
self.toggleItalic()
handled = True
elif event.key() == Qt.Key_K:
self.colorMenu()
handled = True
elif event.key() == Qt.Key_M:
self.textEffectMenu()
handled = True
elif event.key() == Qt.Key_U:
self.toggleUnderline()
handled = True
if handled:
event.accept()
return
if event.key() in (Qt.Key_Enter, Qt.Key_Return):
self.returnPressed.emit()
event.accept()
else:
QTextEdit.keyPressEvent(self, event)
def colorMenu(self):
pixmap = QPixmap(22, 22)
menu = QMenu("Colour")
for text, color in (
("&Black", Qt.black),
("B&lue", Qt.blue),
("Dark Bl&ue", Qt.darkBlue),
("&Cyan", Qt.cyan),
("Dar&k Cyan", Qt.darkCyan),
("&Green", Qt.green),
("Dark Gr&een", Qt.darkGreen),
("M&agenta", Qt.magenta),
("Dark Mage&nta", Qt.darkMagenta),
("&Red", Qt.red),
("&Dark Red", Qt.darkRed)):
color = QColor(color)
pixmap.fill(color)
action = menu.addAction(QIcon(pixmap), text, self.setColor)
action.setData(color)
self.ensureCursorVisible()
menu.exec_(self.viewport().mapToGlobal(
self.cursorRect().center()))
def setColor(self):
action = self.sender()
if action is not None and isinstance(action, QAction):
color = QColor(action.data())
if color.isValid():
self.setTextColor(color)
def textEffectMenu(self):
format = self.currentCharFormat()
menu = QMenu("Text Effect")
for text, shortcut, data, checked in (
("&Bold", "Ctrl+B", RichTextLineEdit.Bold,
self.fontWeight() > QFont.Normal),
("&Italic", "Ctrl+I", RichTextLineEdit.Italic,
self.fontItalic()),
("Strike &out", None, RichTextLineEdit.StrikeOut,
format.fontStrikeOut()),
("&Underline", "Ctrl+U", RichTextLineEdit.Underline,
self.fontUnderline()),
("&Monospaced", None, RichTextLineEdit.Monospaced,
format.fontFamily() == self.monofamily),
("&Serifed", None, RichTextLineEdit.Serif,
format.fontFamily() == self.seriffamily),
("S&ans Serif", None, RichTextLineEdit.Sans,
format.fontFamily() == self.sansfamily),
("&No super or subscript", None,
RichTextLineEdit.NoSuperOrSubscript,
format.verticalAlignment() ==
QTextCharFormat.AlignNormal),
("Su&perscript", None, RichTextLineEdit.Superscript,
format.verticalAlignment() ==
QTextCharFormat.AlignSuperScript),
("Subs&cript", None, RichTextLineEdit.Subscript,
format.verticalAlignment() ==
QTextCharFormat.AlignSubScript)):
action = menu.addAction(text, self.setTextEffect)
if shortcut is not None:
action.setShortcut(QKeySequence(shortcut))
action.setData(data)
action.setCheckable(True)
action.setChecked(checked)
self.ensureCursorVisible()
menu.exec_(self.viewport().mapToGlobal(
self.cursorRect().center()))
def setTextEffect(self):
action = self.sender()
if action is not None and isinstance(action, QAction):
what = action.data()
if what == RichTextLineEdit.Bold:
self.toggleBold()
return
if what == RichTextLineEdit.Italic:
self.toggleItalic()
return
if what == RichTextLineEdit.Underline:
self.toggleUnderline()
return
format = self.currentCharFormat()
if what == RichTextLineEdit.Monospaced:
format.setFontFamily(self.monofamily)
elif what == RichTextLineEdit.Serif:
format.setFontFamily(self.seriffamily)
elif what == RichTextLineEdit.Sans:
format.setFontFamily(self.sansfamily)
if what == RichTextLineEdit.StrikeOut:
format.setFontStrikeOut(not format.fontStrikeOut())
if what == RichTextLineEdit.NoSuperOrSubscript:
format.setVerticalAlignment(
QTextCharFormat.AlignNormal)
elif what == RichTextLineEdit.Superscript:
format.setVerticalAlignment(
QTextCharFormat.AlignSuperScript)
elif what == RichTextLineEdit.Subscript:
format.setVerticalAlignment(
QTextCharFormat.AlignSubScript)
self.mergeCurrentCharFormat(format)
def toSimpleHtml(self):
htmltext = ""
black = QColor(Qt.black)
block = self.document().begin()
while block.isValid():
iterator = block.begin()
while iterator != block.end():
fragment = iterator.fragment()
if fragment.isValid():
format = fragment.charFormat()
family = format.fontFamily()
color = format.foreground().color()
text=html.escape(fragment.text())
if (format.verticalAlignment() ==
QTextCharFormat.AlignSubScript):
text = "<sub>{0}</sub>".format(text)
elif (format.verticalAlignment() ==
QTextCharFormat.AlignSuperScript):
text = "<sup>{0}</sup>".format(text)
if format.fontUnderline():
text = "<u>{0}</u>".format(text)
if format.fontItalic():
text = "<i>{0}</i>".format(text)
if format.fontWeight() > QFont.Normal:
text = "<b>{0}</b>".format(text)
if format.fontStrikeOut():
text = "<s>{0}</s>".format(text)
if color != black or family:
attribs = ""
if color != black:
attribs += ' color="{0}"'.format(color.name())
if family:
attribs += ' face="{0}"'.format(family)
text = "<font{0}>{1}</font>".format(attribs,text)
htmltext += text
iterator += 1
block = block.next()
return htmltext
if __name__ == "__main__":
def printout(lineedit):
print(str(lineedit.toHtml()))
print(str(lineedit.toPlainText()))
print(str(lineedit.toSimpleHtml()))
app = QApplication(sys.argv)
lineedit = RichTextLineEdit()
lineedit.returnPressed.connect(lambda:printout(lineedit))
lineedit.show()
lineedit.setWindowTitle("RichTextEdit")
app.exec_()
/home/yrd/eric_workspace/chap16/genericdelegates.py
#!/usr/bin/env python3
from PyQt5.QtCore import (QDate, QSize, Qt)
from PyQt5.QtWidgets import (QApplication, QDateEdit, QLineEdit,
QSpinBox, QStyledItemDelegate,QStyle)
from PyQt5.QtGui import QColor,QTextDocument
import richtextlineedit
class GenericDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
super(GenericDelegate, self).__init__(parent)
self.delegates = {}
def insertColumnDelegate(self, column, delegate):
delegate.setParent(self)
self.delegates[column] = delegate
def removeColumnDelegate(self, column):
if column in self.delegates:
del self.delegates[column]
def paint(self, painter, option, index):
delegate = self.delegates.get(index.column())
if delegate is not None:
delegate.paint(painter, option, index)
else:
QStyledItemDelegate.paint(self, painter, option, index)
def createEditor(self, parent, option, index):
delegate = self.delegates.get(index.column())
if delegate is not None:
return delegate.createEditor(parent, option, index)
else:
return QStyledItemDelegate.createEditor(self, parent, option,
index)
def setEditorData(self, editor, index):
delegate = self.delegates.get(index.column())
if delegate is not None:
delegate.setEditorData(editor, index)
else:
QStyledItemDelegate.setEditorData(self, editor, index)
def setModelData(self, editor, model, index):
delegate = self.delegates.get(index.column())
if delegate is not None:
delegate.setModelData(editor, model, index)
else:
QStyledItemDelegate.setModelData(self, editor, model, index)
class IntegerColumnDelegate(QStyledItemDelegate):
def __init__(self, minimum=0, maximum=100, parent=None):
super(IntegerColumnDelegate, self).__init__(parent)
self.minimum = minimum
self.maximum = maximum
def createEditor(self, parent, option, index):
spinbox = QSpinBox(parent)
spinbox.setRange(self.minimum, self.maximum)
spinbox.setAlignment(Qt.AlignRight|Qt.AlignVCenter)
return spinbox
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.DisplayRole)
editor.setValue(value)
def setModelData(self, editor, model, index):
editor.interpretText()
model.setData(index, editor.value())
class DateColumnDelegate(QStyledItemDelegate):
def __init__(self, minimum=QDate(),
maximum=QDate.currentDate(),
format="yyyy-MM-dd", parent=None):
super(DateColumnDelegate, self).__init__(parent)
self.minimum = minimum
self.maximum = maximum
self.format = format
def createEditor(self, parent, option, index):
dateedit = QDateEdit(parent)
#dateedit=QDateTimeEdit(parent)
dateedit.setDateRange(self.minimum, self.maximum)
dateedit.setAlignment(Qt.AlignRight|Qt.AlignVCenter)
dateedit.setDisplayFormat(self.format)
dateedit.setCalendarPopup(True)
return dateedit
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.DisplayRole)
#if value.isNull:
editor.setDate(value)
#editor.setDisplayFormat(self.format)
def setModelData(self, editor, model, index):
model.setData(index, editor.date())
def paint(self, painter, option, index):
text = index.model().data(index, Qt.DisplayRole).toString(self.format)
palette = QApplication.palette()
document = QTextDocument()
document.setDefaultFont(option.font)
if option.state & QStyle.State_Selected:
document.setHtml("<font color={0}>{1}</font>".format(palette.highlightedText().color().name(),text))
else:
document.setHtml(text)
painter.save()
color = (palette.highlight().color()
if option.state & QStyle.State_Selected
else QColor(index.model().data(index,
Qt.BackgroundColorRole)))
painter.fillRect(option.rect, color)
painter.translate(option.rect.x(), option.rect.y())
document.drawContents(painter)
painter.restore()
class PlainTextColumnDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
super(PlainTextColumnDelegate, self).__init__(parent)
def createEditor(self, parent, option, index):
lineedit = QLineEdit(parent)
return lineedit
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.DisplayRole)
editor.setText(value)
def setModelData(self, editor, model, index):
model.setData(index, editor.text())
class RichTextColumnDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
super(RichTextColumnDelegate, self).__init__(parent)
def paint(self, painter, option, index):
text = index.model().data(index, Qt.DisplayRole)
palette = QApplication.palette()
document = QTextDocument()
document.setDefaultFont(option.font)
if option.state & QStyle.State_Selected:
document.setHtml("<font color={0}>{1}</font>".format(palette.highlightedText().color().name(),text))
else:
document.setHtml(text)
painter.save()
color = (palette.highlight().color()
if option.state & QStyle.State_Selected
else QColor(index.model().data(index,
Qt.BackgroundColorRole)))
painter.fillRect(option.rect, color)
painter.translate(option.rect.x(), option.rect.y())
document.drawContents(painter)
painter.restore()
def sizeHint(self, option, index):
text = index.model().data(index).toString()
document = QTextDocument()
document.setDefaultFont(option.font)
document.setHtml(text)
return QSize(document.idealWidth() + 5,
option.fontMetrics.height())
def createEditor(self, parent, option, index):
lineedit = richtextlineedit.RichTextLineEdit(parent)
return lineedit
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.DisplayRole)
editor.setHtml(value)
def setModelData(self, editor, model, index):
model.setData(index, editor.toSimpleHtml())
/home/yrd/eric_workspace/chap16/carhirelog.pyw
#!/usr/bin/env python3
import bisect
import os
import platform
import sys
from PyQt5.QtCore import (QAbstractTableModel, QDate, QModelIndex,
QVariant, Qt,pyqtSignal)
from PyQt5.QtWidgets import (QApplication, QMainWindow,
QShortcut, QTableView)
from PyQt5.QtGui import QKeySequence
import genericdelegates
(LICENSE, CUSTOMER, HIRED, MILEAGEOUT, RETURNED, MILEAGEBACK,
NOTES, MILEAGE, DAYS) = range(9)
class CarHireLog(object):
def __init__(self, license, customer, hired, mileageout,
returned=QDate(), mileageback=0, notes=""):
self.license = license # plain text
self.customer = customer # plain text
self.hired = hired # QDate
self.mileageout = mileageout # int
self.returned = returned # QDate
self.mileageback = mileageback # int
self.notes = notes # HTML
def field(self, column):
if column == LICENSE:
return self.license
elif column == CUSTOMER:
return self.customer
elif column == HIRED:
return self.hired
elif column == MILEAGEOUT:
return self.mileageout
elif column == RETURNED:
return self.returned
elif column == MILEAGEBACK:
return self.mileageback
elif column == NOTES:
return self.notes
elif column == MILEAGE:
return self.mileage()
elif column == DAYS:
return self.days()
assert False
def mileage(self):
return (0 if self.mileageback == 0
else self.mileageback - self.mileageout)
def days(self):
return (0 if not self.returned.isValid()
else self.hired.daysTo(self.returned))
def __hash__(self):
return super(CarHireLog, self).__hash__()
def __eq__(self, other):
if self.hired != other.hired:
return False
if self.customer != other.customer:
return False
if self.license != other.license:
return False
return id(self) == id(other)
def __lt__(self, other):
if self.hired < other.hired:
return True
if self.customer < other.customer:
return True
if self.license < other.license:
return True
return id(self) < id(other)
class CarHireModel(QAbstractTableModel):
dataChanged = pyqtSignal(QModelIndex,QModelIndex)
def __init__(self, parent=None):
super(CarHireModel, self).__init__(parent)
self.logs = []
# Generate fake data
import gzip
import random
import string
surname_data = gzip.open(os.path.join(
os.path.dirname(__file__), "surnames.txt.gz")).read()
surnames = surname_data.decode("utf8").splitlines()
years = ("06 ", "56 ", "07 ", "57 ", "08 ", "58 ")
titles = ("Ms ", "Mr ", "Ms ", "Mr ", "Ms ", "Mr ", "Dr ")
notetexts = ("Returned <font color=red><b>damaged</b></font>",
"Returned with <i>empty fuel tank</i>",
"Customer <b>complained</b> about the <u>engine</u>",
"Customer <b>complained</b> about the <u>gears</u>",
"Customer <b>complained</b> about the <u>clutch</u>",
"Returned <font color=darkred><b>dirty</b></font>",)
today = QDate.currentDate()
for i in range(250):
license = []
for c in range(5):
license.append(random.choice(string.ascii_uppercase))
license = ("".join(license[:2]) + random.choice(years) +
"".join(license[2:]))
customer = random.choice(titles) + random.choice(surnames)
hired = today.addDays(-random.randint(0, 365))
mileageout = random.randint(10000, 30000)
notes = ""
if random.random() >= 0.2:
days = random.randint(1, 21)
returned = hired.addDays(days)
mileageback = (mileageout +
(days * random.randint(30, 300)))
if random.random() > 0.75:
notes = random.choice(notetexts)
else:
returned = QDate()
mileageback = 0
log = CarHireLog(license, customer, hired, mileageout,
returned, mileageback, notes)
bisect.insort(self.logs, log)
def rowCount(self, index=QModelIndex()):
return len(self.logs)
def columnCount(self, index=QModelIndex()):
return 9
def data(self, index, role):
if not index.isValid():
return QVariant()
if role == Qt.DisplayRole:
log = self.logs[index.row()]
value = log.field(index.column())
if (index.column() in (MILEAGEBACK, MILEAGE, DAYS) and
value == 0):
return 0
return value
if (role == Qt.TextAlignmentRole and
index.column() not in (LICENSE, CUSTOMER, NOTES)):
return QVariant(int(Qt.AlignRight|Qt.AlignVCenter))
if role == Qt.BackgroundColorRole:
palette = QApplication.palette()
if index.column() in (LICENSE, MILEAGE, DAYS):
return QVariant(palette.alternateBase())
else:
return QVariant(palette.base())
return QVariant()
def setData(self, index, value, role=Qt.EditRole):
if (index.isValid() and role == Qt.EditRole and
index.column() not in (LICENSE, MILEAGE, DAYS)):
log = self.logs[index.row()]
column = index.column()
if column == CUSTOMER:
log.customer = value
elif column == HIRED:
#log.hired = value.toDate()
log.hired = value
elif column == MILEAGEOUT:
log.mileageout = value
elif column == RETURNED:
#log.returned = value.toDate()
log.returned = value
elif column == MILEAGEBACK:
log.mileageback = value
elif column == NOTES:
log.notes = value
self.dataChanged[QModelIndex,QModelIndex].emit(index,index)
return True
return False
def headerData(self, section, orientation, role):
if role == Qt.TextAlignmentRole:
if orientation == Qt.Horizontal:
return QVariant(int(Qt.AlignCenter))
return QVariant(int(Qt.AlignRight|Qt.AlignVCenter))
if role != Qt.DisplayRole:
return QVariant()
if orientation == Qt.Horizontal:
if section == LICENSE:
return "License"
elif section == CUSTOMER:
return "Customer"
elif section == HIRED:
return "Hired"
elif section == MILEAGEOUT:
return "Mileage #1"
elif section == RETURNED:
return "Returned"
elif section == MILEAGEBACK:
return "Mileage #2"
elif section == DAYS:
return "Days"
elif section == MILEAGE:
return "Miles"
elif section == NOTES:
return "Notes"
return section + 1
def flags(self, index):
flag = QAbstractTableModel.flags(self, index)
if index.column() not in (LICENSE, MILEAGE, DAYS):
flag |= Qt.ItemIsEditable
return flag
class HireDateColumnDelegate(genericdelegates.DateColumnDelegate):
def createEditor(self, parent, option, index):
i = index.sibling(index.row(), RETURNED)
self.maximum = i.model().data(i, Qt.DisplayRole).addDays(-1)
return genericdelegates.DateColumnDelegate.createEditor(
self, parent, option, index)
class ReturnDateColumnDelegate(genericdelegates.DateColumnDelegate):
def createEditor(self, parent, option, index):
i = index.sibling(index.row(), HIRED)
self.minimum = i.model().data(i, Qt.DisplayRole).addDays(1)
return genericdelegates.DateColumnDelegate.createEditor(
self, parent, option, index)
class MileageOutColumnDelegate(genericdelegates.IntegerColumnDelegate):
def createEditor(self, parent, option, index):
i = index.sibling(index.row(), MILEAGEBACK)
maximum = i.model().data(i, Qt.DisplayRole)
self.maximum = 1000000 if maximum == 0 else maximum - 1
return genericdelegates.IntegerColumnDelegate.createEditor(
self, parent, option, index)
class MileageBackColumnDelegate(genericdelegates.IntegerColumnDelegate):
def createEditor(self, parent, option, index):
i = index.sibling(index.row(), MILEAGEOUT)
self.minimum = i.model().data(i, Qt.DisplayRole) + 1
return genericdelegates.IntegerColumnDelegate.createEditor(
self, parent, option, index)
class MainForm(QMainWindow):
def __init__(self, parent=None):
super(MainForm, self).__init__(parent)
model = CarHireModel(self)
self.view = QTableView()
self.view.setModel(model)
self.view.resizeColumnsToContents()
delegate = genericdelegates.GenericDelegate(self)
delegate.insertColumnDelegate(CUSTOMER,
genericdelegates.PlainTextColumnDelegate())
earliest = QDate.currentDate().addYears(-3)
delegate.insertColumnDelegate(HIRED,
HireDateColumnDelegate(earliest))
delegate.insertColumnDelegate(MILEAGEOUT,
MileageOutColumnDelegate(0, 1000000))
delegate.insertColumnDelegate(RETURNED,
ReturnDateColumnDelegate(earliest))
delegate.insertColumnDelegate(MILEAGEBACK,
MileageBackColumnDelegate(0, 1000000))
delegate.insertColumnDelegate(NOTES,
genericdelegates.RichTextColumnDelegate())
self.view.setItemDelegate(delegate)
self.setCentralWidget(self.view)
QShortcut(QKeySequence("Escape"), self, self.close)
QShortcut(QKeySequence("Ctrl+Q"), self, self.close)
self.setWindowTitle("Car Hire Logs")
app = QApplication(sys.argv)
form = MainForm()
rect = QApplication.desktop().availableGeometry()
form.resize(int(rect.width() * 0.7), int(rect.height() * 0.8))
form.move(0, 0)
form.show()
app.exec_()
運(yùn)行結(jié)果:

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
pytorch基礎(chǔ)之損失函數(shù)與反向傳播詳解
損失函數(shù)(Loss?Function)用于衡量神經(jīng)網(wǎng)絡(luò)輸出與目標(biāo)值之間的誤差,指導(dǎo)網(wǎng)絡(luò)通過反向傳播優(yōu)化參數(shù),常見的損失函數(shù)包括均方誤差和交叉熵誤差,在訓(xùn)練過程中,通過不斷最小化損失函數(shù)值來調(diào)整網(wǎng)絡(luò)權(quán)重,以期達(dá)到輸出接近目標(biāo)值的效果2024-09-09
基于Python的身份證驗(yàn)證識別和數(shù)據(jù)處理詳解
這篇文章主要介紹了基于Python的身份證驗(yàn)證識別和數(shù)據(jù)處理,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
pip安裝py_zipkin時(shí)提示的SSL問題對應(yīng)
今天小編就為大家分享一篇關(guān)于pip安裝py_zipkin時(shí)提示的SSL問題對應(yīng),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12
Python使用Flask框架同時(shí)上傳多個(gè)文件的方法
這篇文章主要介紹了Python使用Flask框架同時(shí)上傳多個(gè)文件的方法,實(shí)例分析了Python中Flask框架操作文件實(shí)現(xiàn)上傳的技巧,需要的朋友可以參考下2015-03-03
使用python創(chuàng)建股票的時(shí)間序列可視化分析
這篇文章主要為大家詳細(xì)介紹了python創(chuàng)建股票的時(shí)間序列可視化分析,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03
python處理multipart/form-data的請求方法
今天小編就為大家分享一篇python處理multipart/form-data的請求方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12

