python - 调用方法和调整按钮文本
问题描述
我正在尝试结合 PyQt5 和 Qt Designer 制作一个膳食调度程序(最终这将从数据库中生成一个购物清单)。膳食计划是一个由 7 x 3 个按钮组成的网格(7 天,每天 3 顿饭)——总共 21 个按钮。
当用户单击膳食计划中的按钮(“SelMealButtons”之一)时,会打开一个弹出窗口,其中包含可供选择的膳食列表(这是代码中的 Selector 类)。用户选择一餐并使用“OK”按钮(以下代码中的“pushButton”)确认他们的选择。
我试图通过“set_button_labels”方法让餐点名称作为相应的按钮文本显示在餐点计划中。为简单起见,示例代码中仅引用了 21 个“SelMealButtons”中的三个,如下所示:
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon
from PyQt5 import uic
from PyQt5 import QtCore
from PyQt5.QtCore import pyqtSignal, pyqtSlot
uifile_1 = 'untitled3.ui'
form_1, base_1 = uic.loadUiType(uifile_1)
uifile_2 = 'untitled2.ui'
form_2, base_2 = uic.loadUiType(uifile_2)
array = ["Meal 1", "Meal 2", "Meal 3"]
meal_schedule = [""]*21
class Schedule(base_1, form_1):
def __init__(self):
super(base_1,self).__init__()
self.setupUi(self)
self.SelMealButton.clicked.connect(lambda: self.m_b_pressed(0))
self.SelMealButton_2.clicked.connect(lambda: self.m_b_pressed(1))
self.SelMealButton_3.clicked.connect(lambda: self.m_b_pressed(2))
def m_b_pressed(self, button_no):
self.selector = Selector()
self.selector.show()
self.selector.pushButton.clicked.connect(lambda: self.selector.OKbutton(button_no))
def set_button_labels(self, message):
print(message)
self.SelMealButton.setText(meal_schedule[0])
self.SelMealButton_2.setText(meal_schedule[1])
self.SelMealButton_3.setText(meal_schedule[2])
class Selector(base_2, form_2):
def __init__(self):
super(base_2, self).__init__()
self.setupUi(self)
for item in array:
self.listWidget.addItem(item)
self.pushButton_2.clicked.connect(self.closewindow)
def closewindow(self):
self.close()
self.schedule = Schedule()
def OKbutton(self, button_no):
x = self.listWidget.currentRow()
y = str(array[x])
meal_schedule[button_no] = y
self.schedule = Schedule()
self.schedule.set_button_labels(y)
self.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
s = Schedule()
s.show()
sys.exit(app.exec_())
用户界面文件如下:
无标题3.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>234</width>
<height>339</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="SelMealButton">
<property name="geometry">
<rect>
<x>70</x>
<y>60</y>
<width>131</width>
<height>51</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLabel" name="MealtimeLabel">
<property name="geometry">
<rect>
<x>10</x>
<y>80</y>
<width>51</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Breakfast</string>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>120</x>
<y>40</y>
<width>21</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Mon</string>
</property>
</widget>
<widget class="QPushButton" name="SelMealButton_2">
<property name="geometry">
<rect>
<x>70</x>
<y>120</y>
<width>131</width>
<height>51</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QPushButton" name="SelMealButton_3">
<property name="geometry">
<rect>
<x>70</x>
<y>180</y>
<width>131</width>
<height>51</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>10</x>
<y>140</y>
<width>47</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>Lunch</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>10</x>
<y>200</y>
<width>47</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>Dinner</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>234</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
和untitled2.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QListWidget" name="listWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>256</width>
<height>281</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>290</x>
<y>20</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>OK</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_2">
<property name="geometry">
<rect>
<x>290</x>
<y>60</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
只要从“Selector”类调用“OKbutton”方法,它就可以将listWidget 值分配给meal_schedule 数组。我知道(通过测试)这个方法反过来又在 Schedule 类中调用“set_button_labels”方法。但是,“set_button_labels”方法不会根据需要调整 SelMealButtons 的文本***。是否有人能够就为什么会这样和/或我如何实现此功能提出任何建议?
我已经开始阅读有关插槽和信号的内容,但很难理解它。
***(解决此问题的一种方法是在调用 Selector 小部件时关闭 Schedule 窗口 - 然后在 Selector 小部件关闭时再次打开它。但是我更愿意保持 Schedule 窗口保持打开状态。)
解决方案
问题是,每次调用时,OKbutton
您都在创建一个新实例,并且在该Schedule
实例上设置按钮文本,而不是主实例。此外,该实例从未实际显示(同样发生在 中)。close_window()
您需要做的是跟踪当前按钮并连接到选择器的“ok”按钮,以便正确更新值。以下是您的示例的可能重新实现:
array = ["Meal 1", "Meal 2", "Meal 3"]
days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"]
# a simple example of meals "array" with the format "day meal"
meal_schedule = ["{} {}".format(d, m) for d in days for m in array]
class Schedule(base_1, form_1):
def __init__(self):
super(base_1,self).__init__()
self.setupUi(self)
self.SelMealButton.clicked.connect(lambda: self.m_b_pressed(0))
self.SelMealButton_2.clicked.connect(lambda: self.m_b_pressed(1))
self.SelMealButton_3.clicked.connect(lambda: self.m_b_pressed(2))
self.selector = Selector()
self.selector.pushButton.clicked.connect(self.set_button_labels)
self.buttons = (
self.SelMealButton,
self.SelMealButton_2,
self.SelMealButton_3
)
# example, wednesday
self.current_day = 2
def m_b_pressed(self, button_no):
self.current_meal_button = self.buttons[button_no]
self.selector.show()
def set_button_labels(self):
index = self.selector.listWidget.currentRow() + self.current_day * 3
meal = meal_schedule[index]
self.current_meal_button.setText(meal)
class Selector(base_2, form_2):
def __init__(self):
super(base_2, self).__init__()
self.setupUi(self)
for item in array:
self.listWidget.addItem(item)
self.pushButton_2.clicked.connect(self.close)
self.pushButton.clicked.connect(self.close)
请注意,您的实现有两个重要问题。
- Selector 窗口可能应该是一个模式对话框,它会阻止与其他窗口的交互,直到它关闭:使用您当前的代码,用户可以在显示 Selector 时在 Schedule 中选择不同的餐点,这会使事情变得非常混乱。在 Designer 中创建一个新对话框(已定义按钮的两个对话框之一),然后使用以下命令调用它
exec_
:
class Schedule(base_1, form_1):
def __init__(self):
super(base_1,self).__init__()
self.setupUi(self)
self.SelMealButton.clicked.connect(lambda: self.m_b_pressed(0))
self.SelMealButton_2.clicked.connect(lambda: self.m_b_pressed(1))
self.SelMealButton_3.clicked.connect(lambda: self.m_b_pressed(2))
# not needed anymore
# self.selector = Selector()
# self.selector.pushButton.clicked.connect(self.set_button_labels)
self.buttons = (
self.SelMealButton,
self.SelMealButton_2,
self.SelMealButton_3
)
self.current_day = 2
def m_b_pressed(self, button_no):
selector = Selector(self)
if selector.exec_():
index = selector.listWidget.currentRow() + self.current_day * 3
meal = meal_schedule[index]
self.buttons[button_no].setText(meal)
class Selector(base_2, form_2):
def __init__(self):
super(base_2, self).__init__()
self.setupUi(self)
for item in array:
self.listWidget.addItem(item)
- 即使它与手头的问题无关,通常也不鼓励使用固定的几何图形,而应始终使用布局管理器。一个简单的原因是我能够缩小两个窗口,并且在一定尺寸以下界面变得无法使用。
推荐阅读
- php - PI Server 未完成 1000 个 SQL 查询的 php 代码
- python - 在散景中更改轴的股票标签
- node.js - 带有nodejs的docker(运行pm2)和postgresql
- microsoft-graph-api - 为 OneDrive DriveItem 创建可下载链接和预览文件
- android - 无法解决任何依赖项导入
- hadoop - 如果我在 hive 的所有列上使用 distinct,将运行多少个 reducer?
- c++ - 从标准容器重新绑定和复制分配器
- angular - Angular 5 Oauth2.0 基本身份验证 POST 请求返回 401(未经授权)
- c++ - create_directory() 与 create_directories()
- ruby-on-rails - 如何在 Elasticsearch 中将关键字更改为数字?