学Python:从QFormLayout布局中取部件的值
![e44ace11d54587129d704c12d339fe7e.png](https://i-blog.csdnimg.cn/blog_migrate/e91ae49d8bcc5dfc30f697645f39a211.jpeg)
练习一个记账小程序,涉及到QTableWidget表格、SQLite数据库, QTabWidget、setStyleSheet、lambda插槽信号传递,setValidator验证器,QInputDialog预设值,Icon等许多东西,今天用另类方法从QFormLayout布局中取部件的值完成记账入库。
先把主程序搭起来:
# *-- utf8 --*# 练习做一个综合性的家庭记账小程序# 4个页面:概览,记账,查询,设置# 涉及从QFormLayout布局中取部件的值、QTableWidget表格、SQLite数据库# QTabWidget、setStyleSheet、lambda插槽信号传递# setValidator验证器,QInputDialog预设值,Icon# QSqlTableModel,QTableViewfrom PyQt5.QtWidgets import *from PyQt5.QtGui import *from PyQt5.QtCore import *from PyQt5.QtSql import *import sqlite3import timeimport sysclass ACT(QWidget): def __init__(self): super().__init__() self.setGUI() def setGUI(self): self.setGeometry(200, 0, 280, 400) self.setStyleSheet("QPushButton{width:60;}") self.icon = QPushButton() self.icon.setFont(QFont('微软雅黑', 16)) self.icon.setMaximumWidth(18) self.icon.setStyleSheet("background-image:url('hanghui.png');" "background-repeat: no-repeat;background-position:center;" "background-color: LightSeaGreen;" "color: White;border:none;") self.title = QLabel('记账本') self.title.setWindowIcon(QIcon('hanghui.png')) # 绑定图标文件 self.title.setFont(QFont('微软雅黑', 16)) self.title.setAlignment(Qt.AlignCenter) self.title.setStyleSheet("background-color: LightSeaGreen;color: White;") self.exbt = QPushButton('×') self.exbt.setFont(QFont('微软雅黑', 16)) self.exbt.setMaximumWidth(18) self.exbt.setStyleSheet("background-color: LightSeaGreen;color: White;border:none;") self.layout1 = QHBoxLayout() # 第一行标题布局 self.layout1.addWidget(self.icon) self.layout1.addWidget(self.title) self.layout1.addWidget(self.exbt) self.layout1.setSpacing(0) self.date = QLabel() # 第二行显示日期布局 self.date.setText(time.strftime(' %Y年%m月%d日', time.localtime(time.time()))) self.tab1 = QLabel() # 创建表格(第一页) self.tab = QTabWidget() # 四个页面的容器 self.tab.addTab(self.set_tab1(), '概览') self.tab.addTab(self.set_tab2(), '记账') self.tab.addTab(self.set_tab3(), '查询') self.tab.addTab(self.set_tab4(), '设置') # self.frame.setTabPosition(QTabWidget.South) # 标签放在底部 self.tab.setContentsMargins(0, 0, 0, 0) self.layout = QVBoxLayout() # 总布局 self.layout.addLayout(self.layout1) # 第一行加入布局 self.layout.addWidget(self.date) # 第二行日期加入布局 self.layout.addWidget(self.tab) # 第三标签组件加入布局 self.layout.addStretch() self.layout.setContentsMargins(0, 0, 0, 0) # 窗口边距设为 0 self.setLayout(self.layout) self.setWindowFlags(Qt.FramelessWindowHint) # 无边框 self.exbt.clicked.connect(QCoreApplication.instance().quit) # 关闭按钮 self.show()def set_tab1(self): # 第一页 tab1=QLabel(‘第一页’) return tab1def set_tab2(self): # 第二页 # 这里填子模块代码def set_tab3(self): # 第三页 tab3=QLabel(‘第三页’) return tab3def set_tab3(self): # 第四页 tab4=QLabel(‘第四页’) return tab4if __name__ == '__main__': app = QApplication(sys.argv) app.setStyle('Fusion') ex = ACT() sys.exit(app.exec_())
下面把记账模块set_tab2代码填进去:
def set_tab2(self): self.dateEdit = QDateEdit(QDate.currentDate()) # 第一行 指定当前日期为控件的日期 self.member = QComboBox() self.inORcost = QComboBox() self.subject = QComboBox() self.enterMoney = QLineEdit() self.enterComment = QLineEdit() self.dateEdit.setDisplayFormat("yyyy-MM-dd") tableName = ['income', 'cost'] self.inORcost.addItems(['收入', '支出']) self.inORcost.setCurrentIndex(1) # 第二行 收/支 command = 'select * from %s' % ('member') member_Data = self.sql_command(command) # 获取第三行成员数据 for index in range(len(member_Data)): # 数据填入第三行组合框 self.member.addItem(str(member_Data[index][0])) self.getSubject(tableName[self.inORcost.currentIndex()]) self.inORcost.currentIndexChanged.connect(lambda :self.getSubject(tableName[self.inORcost.currentIndex()]) ) # 收支选项变动发信号科目变动 self.layoutForm = QFormLayout() self.layoutForm.addRow('日期', self.dateEdit) # 项目填入表格单元 self.layoutForm.addRow('收支', self.inORcost) self.layoutForm.addRow('成员', self.member) self.layoutForm.addRow('科目', self.subject) self.layoutForm.addRow('金额', self.enterMoney) self.layoutForm.addRow('备注', self.enterComment) pDoubleValidator = QDoubleValidator() # 设置输入数字合法验证 pDoubleValidator.setNotation(QDoubleValidator.StandardNotation) # 设置精度小数点后两位 pDoubleValidator.setDecimals(2) self.enterMoney.setValidator(pDoubleValidator) setbtSave = QPushButton('保存') # 第二页第3项 setbtSave.clicked.connect(self.addAccept) # 按钮绑定 # 第二页布局整合 layout2 = QVBoxLayout() layout2.addLayout(self.layoutForm) layout2.addStretch() layout2.addWidget(setbtSave) tab2 = QWidget() # 第二页 tab2.setLayout(layout2) return tab2
上面代码中用QDoubleValidator()限制金额栏只能输入带2位小数的浮点数,不能输入其他字符。
下面是保存按钮对应的事件处理模块,这里用try-except取FormLayout包含的组件的值,可以消除不同组件的不同属性造成的程序异常:
def addAccept(self): # 输入项不为空表示输入正确 if self.enterMoney.text() != '': lt = [] # 取出表单布局中输入的值 for i in range(1, self.layoutForm.count(), 2): item = self.layoutForm.itemAt(i) t = '' try: t = item.widget().text() except: try: t = item.widget().currentText() except: pass lt.append(t) #print(lt) header = self.getHeader('account') subject = '' for h in header: # 取字段列表 subject = subject + h + ',' subject = subject[:-1] value = '' for h in lt: value = value + "'" + h + "'," value = value[:-1] conn = sqlite3.connect('account.db') curs = conn.cursor() command = "CREATE TABLE IF NOT EXISTS %s (日期 DATE, 收支 TEXT,成员 TEXT,科目 TEXT,金额 REAL,备注 TEXT);" % (table_name) curs.execute(command) command = "insert into account (%s) values (%s)" % (subject, value) # 在数据库中新增记录 c = curs.execute(command) conn.commit() conn.close() self.showMsg('新增成功') else: self.showMsg('请输入金额')