在另一个类中编辑对象(PyQt5)

huangapple go评论68阅读模式
英文:

Editing an object in another class (PyQt5)

问题

以下是翻译好的内容:

任务:
有两个类。类“First”创建主窗口和按钮。
类“Second”更改由类“First”创建的主窗口上按钮的标签。

出现的问题:
以下是我编写的示例代码。其执行导致创建许多窗口(这是错误的),甚至在这些窗口上也没有绘制按钮(这也是错误的)。
显然,我在引用类时出现错误。但是谷歌和尝试了各种选项后,不幸的是,我没有找到代码中的错误。

import sys
from time import sleep
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton

class First(QMainWindow):
    def __init__(self):
        super(First, self).__init__()
        self.pbutton = QPushButton("First", self)
        self.show()
        self.class_Second = Second()
        self.class_Second.Change()

class Second():
    def __init__(self):
        pass

    def Change(self):
        print("Start Change")
        sleep(3)
        First().pbutton.setText("Second")

app = QApplication(sys.argv)
win = First()
sys.exit(app.exec_())

还有一个问题:
函数“def init(self):”是否只被调用一次?为什么会多次调用“def Change(self):”函数,如果代码没有循环、条件或定时器?
如果将“self.show()”设置得更低,那么我们会再次多次调用函数,但这次主窗口甚至不会出现。

import sys
from time import sleep
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton

class First(QMainWindow):
    def __init__(self):
        super(First, self).__init__()
        self.pbutton = QPushButton("First", self)
        self.class_Second = Second()
        self.class_Second.Change()
        self.show()

class Second():
    def __init__(self):
        pass

    def Change(self):
        print("Start Change")
        sleep(3)
        First().pbutton.setText("Second")

app = QApplication(sys.argv)
win = First()
sys.exit(app.exec_())

更新:
如果添加一个“print()”并查看控制台中的日志,似乎函数并未完全执行,但也没有以错误结束。但是尽管在类调用中存在错误,但多次函数调用仍在继续。

def Change(self):
    print("Start Change")
    sleep(3)
    First().pbutton.setText("Second")
    print("____")

在控制台中看到:

在另一个类中编辑对象(PyQt5)

英文:

Task:
There are two classes. The class «First» creates the main window and button.
The class «Second» changes the label on the button on the main window (created by the class «First»).

What came up:
Below is the code I wrote as an example. The execution of which leads to the creation of many windows (which is wrong), and even a button is not drawn on these windows (which is also wrong).
Obviously, I am referring to the class incorrectly. But google and having tried the options, unfortunately, I did not find an error in the code.

import sys
from time import sleep

from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton

class First(QMainWindow):
    def __init__(self):
        super(First, self).__init__()
        self.pbutton = QPushButton("First", self)
        self.show()
        self.class_Second = Second()
        self.class_Second.Change()

class Second():
    def __init__(self):
        pass

    def Change(self):
        print("Start Change")
        sleep(3)
        First().pbutton.setText("Second")

app = QApplication(sys.argv)
win = First()
sys.exit(app.exec_())

Also a question:
is the function «def __init __ (self):» called once? Why are there multiple calls to the «def Change (self):» function: if the code has no loops, no conditions, no timers?

If the «self.show()» is set lower, then we get again multiple calls to the function, but this time the main window does not even appear.

import sys
from time import sleep

from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton

class First(QMainWindow):
    def __init__(self):
        super(First, self).__init__()
        self.pbutton = QPushButton("First", self)
        self.class_Second = Second()
        self.class_Second.Change()
        self.show()

class Second():
    def __init__(self):
        pass

    def Change(self):
        print("Start Change")
        sleep(3)
        First().pbutton.setText("Second")

app = QApplication(sys.argv)
win = First()
sys.exit(app.exec_())

UPD
If you add a «print()» and look at the log in the console, it seems that the function is not fully executed, but it does not end with an error. But the multiple function call continues, despite the error in the class call.

def Change(self):
    print("Start Change")
    sleep(3)
    First().pbutton.setText("Second")
    print("____")

And in the console:

在另一个类中编辑对象(PyQt5)

答案1

得分: 1

以下是您要翻译的内容:

该语句 First().pbutton.setText('Second') 创建了一个新的 First 实例,并尝试设置新实例的按钮文本。它不会更新任何现有的 First 实例。然而,由于 First.__init__() 调用了 Second.Change(),而 Second.Change() 又调用了 First(),它会调用 First.__init__(),然后调用 Second.Change(),依此类推,最终陷入无限循环。解决这个问题的一种方法是将原始的 First 实例作为参数传递给 Second.Change()

您代码的另一个问题是 Second.Change 中的 sleep 会阻塞代码的执行,直到标签被更改。相反,您可以使用单次触发的 QTimer 来延迟标签的更改而不阻塞代码,例如:

class First(QMainWindow):
    def __init__(self):
        super(First, self).__init__()
        self.pbutton = QPushButton("First", self)
        self.class_Second = Second()
        self.class_Second.Change(self)
        self.show()

class Second():
    def __init__(self):
        pass

    def Change(self, first):
        print("Start Change")
        QTimer.singleShot(3000, lambda: first.pbutton.setText("Second"))

请注意,我已经将代码中的 " 替换为正常的双引号。

英文:

The statement First().pbutton.setText('Second') creates a new instance of First and attempts to set the button text of the new instance. It doesn't update any existing instances of First. However, since First.__init__() calls Second.Change(), and Second.Change() calls First() which calls First.__init__() which calls Second.Change(), etc. you end up in an infinite loop. One way around this is to give the original instance of First as an argument to Second.Change().

The other issue with your code is that sleep in Second.Change will block the execution of your code until after the label has been changed. Instead you could use a singleshot QTimer which will delay the label change without blocking the code, e.g.

class First(QMainWindow):
    def __init__(self):
        super(First, self).__init__()
        self.pbutton = QPushButton("First", self)
        self.class_Second = Second()
        self.class_Second.Change(self)
        self.show()

class Second():
    def __init__(self):
        pass

    def Change(self, first):
        print("Start Change")
        QTimer.singleShot(3000, lambda: first.pbutton.setText("Second"))

答案2

得分: 0

With the help of Heike and myself, I understood how to do it without using QTimer and without using Lambda. I also renamed the variable first to f to avoid confusion with the name of my class First.
工作代码:

import sys
from time import sleep

from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton

class First(QMainWindow):
    def __init__(self):
        super(First, self).__init__()
        self.pbutton = QPushButton("First", self)
        self.class_Second = Second()
        self.class_Second.Change(self)
        self.show()

class Second():
    def __init__(self):
        pass

    def Change(self, f):
        print("Start Change")
        sleep(3)
        f.pbutton.setText("Second")

app = QApplication(sys.argv)
win = First()
sys.exit(app.exec_())
英文:

With help Heike and also I myself understood how to do without QTimer and without Lambda. + variable first renamed on f so that there is no confusion with the name of my class First.
Work code:

import sys
from time import sleep

from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton

class First(QMainWindow):
    def __init__(self):
        super(First, self).__init__()
        self.pbutton = QPushButton("First", self)
        self.class_Second = Second()
        self.class_Second.Change(self)
        self.show()

class Second():
    def __init__(self):
        pass

    def Change(self, f):
        print("Start Change")
        sleep(3)
        f.pbutton.setText("Second")

app = QApplication(sys.argv)
win = First()
sys.exit(app.exec_())

huangapple
  • 本文由 发表于 2020年1月6日 18:18:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/59610282.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定