【问题标题】:PySide signals/slots with iterative loops带有迭代循环的 PySide 信号/槽
【发布时间】:2013-09-25 01:25:01
【问题描述】:

生日快乐!

我正在使用 PySide 开发 Python GUI。我试图实现的功能之一是能够计算系统用户的登录尝试次数。对于使用 input() 命令的非 GUI 应用程序来说,这非常简单,但是我很难理解 self.lineEdit.returnPressed.connect() 命令。

如下所示,我有一个 While 语句,最多允许 3 次登录尝试。但是,如果我尝试使用我通常用于监控键盘输入的方法,例如:

n = 1
while n < 4:
    user_barcode = input()
    if user_barcode == 'James':
        print("Welcome James!")
    else:
        print("User not recognised, please try again.")
        n = n + 1

print("Sorry, you are not a recognised user of this system.")
exit

但是,现在我将 user_barcode 基于 GUI 中的 lineEdit,因此上述方法不起作用。如果我用 self.lineEditScanBarcode.text() 替换 input(),while 语句会自动迭代 3 次,只有 1 个输入到 lineEdit。 IE。我输入一个用户名,按回车,它会自动迭代 3 次。如何在 lineEdit 开始每次迭代之前“请求”输入?

我猜我必须使用信号/插槽意识形态,但是我的理解是我必须使用 self.lineEditScanBarcode.returnPressed.connect() 操作将 lineEdit 输入定向到单独的函数。我在下面试了一下,但它是火车残骸!

def Login(self):
        global user_barcode
        user_barcode = self.lineEditScanBarcode.text()

        i = 1
        while i < 4:

            print(i)

            self.lineEditScanBarcode.returnPressed.connect(LoginAttempt)

            def LoginAttempt(self):

                with open('Users.csv', 'rt') as f:
                    reader = csv.reader(f)
                    for row in reader:
                        for field in row:
                            if field == user_barcode:
                                global row_number
                                row_number = n
                                self.LoggedIn()

                if user_barcode == 'Calibration':
                    self.lineEditScanBarcode.clear()
                    showCalibrationCertificate.show()

                else:
                    if user_barcode not in open('Users.csv', 'r').read():
                        print("Unauthorised access request.")
                        i = i + 1
                        self.lineEditScanBarcode.clear()
                        self.LCDLoginAttempt.display(i-1)
            next

        print("Sorry, you are not an authorised user of this system. Please contact the system administrator for further clarification, or if you feel this is an error.")

我在这里缺少一些明显的技巧吗?我希望有一种方法可以使用 returnPressed 操作,使其行为类似于 input() 操作。这样,我可以在迭代开始时执行 returnPressed 操作,并且脚本在继续之前等待 lineEdit 上按下 enter 键。

有人有什么想法吗?

谢谢!

【问题讨论】:

    标签: python user-interface pyside


    【解决方案1】:

    您缺少(PySide 风格)GUI 编程的最基本部分:事件循环。

    GUI 运行一个主事件循环。每当它找到您为其注册了处理程序的事件时,它就会调用您的处理程序。

    您的处理函数必须尽快返回。它不能坐在那里等待用户输入,或者在它等待的时候没有人在处理任何事件。这意味着没有人会解雇你的下一个connect,因为没有人可以这样做。这也意味着没有人会重新绘制屏幕或响应操作系统检查您的应用是否处于活动状态或其他任何内容。

    这通常意味着您需要将您的逻辑“彻底颠覆”。像这样的:

    def Login(self):
        global user_barcode
        self.login_attempts = 1
        self.lineEditScanBarcode.returnPressed.connect(LoginAttempt)
    
    def LoginAttempt(self):
        user_barcode = self.lineEditScanBarcode.text()
        # all the stuff that validates the barcode
        if valid:
            self.LoggedIn()
            return
        print("Unauthorised access request.")
        self.login_attempts += 1
        self.lineEditScanBarcode.clear()
        self.LCDLoginAttempt.display(self.login_attempts-1)
        if self.login_attempts == 4:
            print("Sorry, you are not an authorised user of this system. Please contact the system administrator for further clarification, or if you feel this is an error.")
            # probably want to do something here... disconnect the signal? quit?
    

    当然,print 语句在 GUI 应用程序中不太可能很有用。还有很多其他的事情看起来很可疑。

    但这是基本思想。你不循环,等待用户进行四次尝试;您注册用户尝试,并保留一个在对您的函数的所有调用之间共享的计数器。

    【讨论】:

    • 我应该规定我对 PySide 和 GUI 非常陌生。我已经阅读了大量的文档,但我还没有掌握事件处理程序的想法。感谢您的详细帖子,这现在更清楚了!我会尝试一下,看看我能想出什么。谢谢!
    • @jars121:第一次编写基于事件循环(或其他异步)的程序时,无论是 GUI 还是网络服务器,都会遇到很大的概念障碍,而且通常教程并不能帮助您克服它。希望现在你知道你在寻找什么,你会很容易地弄清楚它。一旦这个想法在你脑海中响起,这并不难。
    • 谢谢老兄,非常感谢!
    猜你喜欢
    • 2011-10-21
    • 2013-10-22
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    • 1970-01-01
    • 2012-06-08
    相关资源
    最近更新 更多