Unsolved PyQt6 inheritance
-
What is wrong with that inheritance ?
Maybe some parameters or self definitions in Frames ?
Or in__init__
function and parameters in frames
I wanna add to App class grid Layout but in frame one add in that grid START button after clicking on START button load Frame 2 class and delete all widgets from Frame 1 classclass App(QWidget): def __init__(self): super().__init__() # Frames self.frame1 = Frame1(self.start_detection) self.frame2 = Frame2(self.goto_frame1) # Click events self.frame1.start.clicked.connect(self.start_detection) self.frame2.back.clicked.connect(self.goto_frame1) # Create main grid Layout self.grid = QGridLayout() self.icon_app = QIcon() self.icon_app.addFile(u"Photos/Icon.png", QSize(), QIcon.Normal, QIcon.Off) self.setWindowIcon(self.icon_app) self.setWindowTitle("APA Project") self.resize(1200, 900) self.setLayout(self.frame1) self.widgets = { } def clear_widgets(self): for widget in self.widgets: if self.widgets[widget] != []: self.widgets[widget][-1].hide() for i in range(0, len(self.widgets[widget])): self.widgets[widget].pop() # Transition functions def start_detection(self): self.clear_widgets() self.setLayout(self.frame2()) def goto_frame1(self): self.clear_widgets() self.setLayout(self.frame1()) class Frame1(App): def __init__(self, start_detection): super().__init__() self.start = QPushButton("START") self.grid.addWidget(self.start, 0, 0) self.setLayout(self.grid) self.start.clicked.connect(start_detection) class Frame2(App): def __init__(self, goto_frame1): super().__init__() self.back = QPushButton("Back") self.grid.addWidget(self.back, 0, 0) self.setLayout(self.grid) self.back.clicked.connect(goto_frame1) if __name__ == "__main__": app = QApplication(sys.argv) Application = App() Application.show() sys.exit(app.exec())
-
@MAX001 said in PyQt6 inheritance:
What is wrong with that inheritance ?
In what way "wrong with inheritance"?
If it does not behave as you want, have you tried stepping through it under a debugger?
There is a bunch of code, various things might be wrong. For example,
self.frame2()
&self.frame1()
---class App
does not have any methods namedframe2()
orframe1()
. -
@JonB Error
I will change to objectsframe1
andframe2
Thanks -
@MAX001
Recursion error: yourFrame1
&Frame2
inheritApp
class. YourApp
class's__init__()
createsFrame1
&Frame2
instances. Oh dear.I do not know what you are trying to achieve or how you think your code is intended to work.
-
Hi,
Your Frame1 and Frame2 classes are a pretty convoluted way to add QPushButtons to your main widget class. You should drop that useless inheritance (that is wrongly done) and simply build your GUI within your main widget.
-
@SGaist Sorry but how to implement it correctly?
https://stackoverflow.com/questions/21702897/pyqt-class-inheritance I found something like that.
But what to do with constructor__init__
what parameters should I pass -
If you re-read the examples from that thread, you'll see that the additional widget create inherit from QWidget and not from the MainWindow where they are used.
In any case, as I already wrote, you are making things way too complicated for what you want to achieve.
You can do everything in a single class.
-
I wanna create classes because i implemented it thought functions and i have more then 1000 row of code 😬
And I have some similar frames witch i can make as object of Frame 3 for example and add.clicked.connect
event for the necessary buttons related to certain objects
As the result 1 class 3 objects of that class and less code -
Here you seem to go to the other extreme by trying to put everything in separate widgets which is not a good idea.
The part you posted here really does not justify the added complexity you have.
You should draw your UI and then the logic flow.
-
@SGaist Ok, I will have 1 class, what will I put in it?
GridLayout 2 buttons and one image. How can I then replace QWidgets with other widgets and also how to create 3 objects of the same frames through this class. Wouldn't it be the same idea as with functions and 1000 lines of code?
-
Not counting the MainWindow, you need five custom widgets, one for each "Frame" and one for the "title, image, detect" piece.
Based on the green button, you will put these 4 widgets in a QStackedWidget in your MainWindow.
If you want, you can have a "Frame" class that provides the green button in a layout and where you will set the other widgets in so you don't have to repeat that part.
-
@SGaist Thank you very much, I'll try to implement.
-
@SGaist Sorry again!
It's ok with such inheritance ?
Is it possible that Frame2 covers Frame1?class App(QWidget): def __init__(self): super().__init__() self.grid = QGridLayout(self) self.frame1 = Frame1(self) self.frame2 = Frame2(self) self.frame3 = Frame3(self) self.grid.addWidget(self.frame1, 0, 0) self.grid.addWidget(self.frame2, 0, 0) self.grid.addWidget(self.frame3, 0, 0) self.frame2.close() self.frame3.close() def goto_frame1(self): self.frame2.close() self.frame1.show() def goto_frame2(self): self.frame3.close() self.frame2.show() def goto_frame3(self): self.frame2.close() self.frame3.show() def start_detection(self): self.frame1.close() self.frame2.show() class Frame1(QWidget): def __init__(self, parent): super().__init__(parent) self.grid = QGridLayout(self) self.start_button = QPushButton("START", self) self.grid.addWidget(self.start_button, 0, 0) self.start_button.clicked.connect(parent.start_detection) def clear_widgets(self): for i in range(self.grid.count()): self.grid.itemAt(i).widget().setParent(None) class Frame2(QWidget): def __init__(self, parent): super().__init__(parent) self.grid = QGridLayout(self) self.back_button = QPushButton("BACK", self) self.eye_detect_btn = QPushButton("Detect", self) self.grid.addWidget(self.eye_detect_btn, 0, 0) self.grid.addWidget(self.back_button, 1, 0) self.back_button.clicked.connect(parent.goto_frame1) self.eye_detect_btn.clicked.connect(parent.goto_frame3) def clear_widgets(self): for i in range(self.grid.count()): self.grid.itemAt(i).widget().setParent(None) class Frame3(QWidget): def __init__(self, parent): super().__init__(parent) self.grid = QGridLayout(self) self.back_button = QPushButton("BACK", self) self.eye_detect_btn = QPushButton("Frame 3", self) self.grid.addWidget(self.eye_detect_btn, 0, 0) self.grid.addWidget(self.back_button, 1, 0) self.back_button.clicked.connect(parent.goto_frame2) def clear_widgets(self): for i in range(self.grid.count()): self.grid.itemAt(i).widget().setParent(None)
-
-
@jsulm As I understand it, in
QStackedWidget
, all widgets are saved throughout the entire program, thus consuming memory. If it would be possible to delete them and, if necessary, reload them, so that there would always be only 1 or 2QStackedWidget
pages in memory, which would be good. -
While I appreciate your worries about memory consumption, the 4 panels you showed before do not warrant to be deleted and recreated every time.
You might want to give more details about the inner workings of your application so that we can better understand your situation.
-
@SGaist I want to recognize different objects in the application from the picture from the video and in real time through the camera. Now the camera and video are about 20 fps, and it takes up enough memory for processing, and it would be desirable that the application does not take up a lot of additional resources.
Therefore, I want to programm the application as efficiently as possible, but I don’t know what practices professionals use, they do everything through classes, but how, through functions, through
QStackedWidget
. What technique do they use to implement such applications (efficient and fast). -
@MAX001
I would not have thought that these widgets would occupy much memory relative to the image processing.
I am also not convinced that your hiding & showing of widgets is freeing the memory you think it is. -
What amount of memory are we talking about here ?
If your video pipeline eats 1Gb of memory per image then the small amount of widgets you use don't even enter the scale.Professionals, as you say, start by making things work, then optimize. Build the backend that processes the images, benchmark it, see where goes the memory. See if you can do something about that. Then test drive it for your various sources, and again measure.
Your current attempts to optimize your GUI, as already stated several times, is misguided. Make it simple, make it work, and only once you have something simple and clean will you see if there's really a need to do all these deletions/real-showing. As my fellows already wrote, deletion is not guaranteed to happen immediately and the memory released is not guaranteed to be returned to the OS instantly either.
-