cookeh_a9 | 2020-12-05 00:13:58 UTC | #1
I've been working on a PyQT5 which has vertical tabs. However I am experiencing some odd behavior.
I have a class which inherits QApplication. When I create tabs within this class, behavior is as expected. However I want to add tabs via an event listener call. So within the class that inherits QApplication, I register a function which adds a tab.
When I add a tab via event listener call, the tab window goes outside the MainWindow. However if I just add it manually without event listener calls, the behavior is as expected.
Good and bad behaviors:
My guess is that I am using an old state of QApplication or MainWindow. I've spent a while trying to debug this and I do not see anyone who has ran into tabs appearing outside issue.
Code is below. I have commented in caps-lock the events. This is a rather sized application, so posting all the code isn't really feasible. I am hoping to get any ideas from anyone. Appreciate it.
class MainWindow(QApplication): def __init__(self, argv): super().__init__(argv) self.logic = None self.logic_thread = None self.basic_routine_cb = None self.advanced_routine_cb = None self.routine_frequency_drop_down = None self.current_action_text = None self.bot_running_time_value = None self.total_rallies_joined_value = None self.time_until_next_routine_value = None self.routine_executed_at_value = None self.bubble_time_checked_value = None self.total_marches_drop_down = None self.help_dialog = None self.login = None self.emulator_port_value = None self.start_stop_button = None self.total_preset_rotation_drop_down = None self.consume_stamina_cb = None self.w = None self.win = MainApplicationWindow() self.initialize_user_interface() def initialize_user_interface(self): QtWidgets.QApplication.setStyle(ProxyStyle()) self.setStyle('Fusion') self.win.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) self.win.setGeometry(0, 0, 650, 525) self.win.setFixedSize(650, 525) self.win.setWindowTitle("Some Title") self.w = TabWidget() self.login = LoginForm(self) tab1 = self.create_new_bot_tab() self.w.addTab(tab1, QtGui.QIcon("./forum/images/RedSquare.png"), "1") self.w.addTab(QWidget(), QtGui.QIcon("zoom.png"), "+") self.w.currentChanged.connect(self.add_new_tab) #changed! event_list.append(self.insert_new_bot_tab) # EVENT LISTENER ADDED HERE self.win.setCentralWidget(self.w) self.win.show() self.login.show() self.w.show() sys.exit(self.exec_()) @pyqtSlot() def add_new_tab(self): try: if Client.socket_connection.connected is False: self.w.setCurrentIndex(self.w.currentIndex() - 1) self.login.show() return if self.w.tabText(self.w.currentIndex()) != '+': return Client.attempt_add_tab() # THIS CALLS A FUNCTION WHICH EVENTUALLY CALLS THE REGISTERED EVENT # IF I CALL self.insert_new_bot_tab() HERE RATHER THAN USING EVENT LISTENER TO CALL IT, BEHAVIOUR IS AS EXPECTED except Exception as e: print(str(e)) # THE REGISTERED EVENT HERE def insert_new_bot_tab(self): tab2 = self.create_new_bot_tab() self.w.insertTab(self.w.currentIndex(), tab2, QtGui.QIcon("./forum/images/RedSquare.png"), str(self.w.currentIndex() + 1)) self.w.blockSignals(True) self.w.setCurrentIndex(self.w.currentIndex() - 1) self.w.blockSignals(False) def create_new_bot_tab(self): wdg = CustomQWidget(self.win, self) layout = QtWidgets.QGridLayout(wdg) index = 0 if self.w.currentIndex() > -1: index = self.w.currentIndex() tabs = QTabWidget() tab1 = StartMenuTab(self.login, self.w, index) tab2 = ProfileTab() tabs.resize(300, 200) # Add tabs tabs.addTab(tab1, "Start") tabs.addTab(tab2, "Profile") layout.addWidget(tabs) return wdg
class CustomQWidget(QWidget): def __init__(self, win, win_instance): super().__init__(win) self.win_instance = win_instance
cookeh_a9 | 2020-12-05 06:40:39 UTC | #2
I'm using a hackish work around for now. If anyone has any idea I would really appreciate feedback!
martin | 2020-12-08 12:08:16 UTC | #3
Hi @cookeh_a9 welcome to the forum!
First up, it's a bit strange to inherit from
QApplication, normally, you'd inherit from
QMainWindow for your main window. You then create an instance of
QApplication directly, create your window, and then start up the app event loop, e.g.
app = QApplication(sys.argv) w = MainWindow() app.exec_()
But I don't think that's the issue here. When you get windows popping out of the main window, it's usually an due to something going wrong with window parents -- any widget without a parent in Qt is a floating window. So if you create a
QTabWidget but don't set a parent (either explicitly, or by adding it to a layout) it will be floating. The same happens if you remove the parent from a widget by setting parent to
Another way you can get caught out is by recreating a widget, e.g. if you have a tab widget as
self.w and then recreate the
self.w = QTabWidget again, the reference to the first tab widget is lost + it is destroyed. All widgets that had it as a parent (i.e. the tabs) are now parent-less and will free-float.
I'd start by checking the parent parameters you're passing to the various widgets when being created. Then double-check you're not recreating any widgets accidentally/unnecessarily.