尝试引用对象时未定义名称x

时间:2019-05-03 14:38:29

标签: python class pyqt5

下面的代码创建一个带有日期选择器的简单窗口,以及一个用于激活其余代码的按钮(尚不是最优雅的按钮,我在这里临时使用全局变量,以便可以访问“处理”脚本它们,这些将很快被删除)

问题是,当我创建MyWindow类的对象时,似乎根本无法在start_processing()调用的函数中访问它。

import calendar
import os
from datetime import date
from glob import glob
from time import time

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QComboBox, QPushButton, QLabel, QErrorMessage


def start_processing():
    start = time()
    files_found: tuple = file_search(month, year, r'O:\test\1 Originals')
    for i in files_found:
        process_file(i)
    duration = time() - start
    window1.set_text(f'Generation of files took {duration:.1f} seconds!')


class MyWindow(object):
    def __init__(self):
        self.app = QApplication([])
        self.progress = QLabel('Foo')
        self.title = 'Bar'
        self.left = 10
        self.top = 10
        self.width = 300
        self.height = 300
        self.error_dialog = QErrorMessage()
        self.setup_ui()

    def setup_ui(self):
        self.app.setStyle('Fusion')
        window = QWidget()
        layout = QVBoxLayout()
        combobox_month = QComboBox()
        combobox_year = QComboBox()
        layout.addWidget(self.progress)
        layout.addWidget(combobox_month)
        layout.addWidget(combobox_year)
        combobox_month.addItems(calendar.month_name[1:13])
        combobox_year.addItems(['2017', '2018', '2019', '2020'])
        combobox_year.setToolTip('Select the year')
        combobox_month.setToolTip('Select the month')
        combobox_month.setCurrentText('January')
        combobox_year.setCurrentText('2019')
        process_button = QPushButton('Process')
        layout.addWidget(process_button)
        window.setLayout(layout)
        combobox_month.currentTextChanged.connect(self.on_combobox_month_changed)
        combobox_year.currentTextChanged.connect(self.on_combobox_year_changed)
        process_button.clicked.connect(self.on_button_clicked)
        window.setGeometry(self.left, self.top, self.width, self.height)
        window.setWindowTitle(self.title)
        window.show()
        self.app.exec_()

    @staticmethod
    def on_button_clicked():
        start_processing()

    @staticmethod
    def on_combobox_month_changed(text):
        global month
        month_lookup = {v: k for k, v in enumerate(calendar.month_name)}
        month = month_lookup[text]

    @staticmethod
    def on_combobox_year_changed(text):
        global year
        year = int(text)

    def set_text(self, text):
        self.progress.setText(text)
        self.app.processEvents()

    def error_message(self, text):
        self.error_dialog.showMessage(text)


if __name__ == '__main__':
    window1 = MyWindow()

如果我随后尝试window1.set_text('Blah'),则在函数start_processing()中会得到一个NameError: name 'window1' is not defined

start_processing是在脚本的主体中定义的,除此类中所包含的功能外,所有功能都已定义。

不确定我需要发布整个脚本的多少,但很高兴添加其他内容。

1 个答案:

答案 0 :(得分:1)

window1 = MyWindow()完全完成执行之前,语句window1不会真正为变量MyWindow()赋值。 MyWindow()必须先执行__init__(),然后才能完成执行。但是首先setup_ui必须完成执行。但是首先exec_必须完成执行。但是exec_会无限期地阻塞,只要窗口保持打开状态即可。因此,当用户单击按钮并触发on_button_clicked时,window1将没有值。

一种可能的解决方案是移动exec_调用,这样__init__()不会直接或间接调用它。例如,您可以在创建MyWindow()之后立即在文件级范围内调用它。

if __name__ == '__main__':
    window1 = MyWindow()
    window1.app.exec_()