Frage

EDIT : I've come up with a solution, and it's much more straightforward than I thought. Original code and question at the top. My solution after "The Question" below..

The Example

from PyQt4 import QtGui, QtCore
from example_Ui import Ui_MainWindow
from filler_Ui import Form


class TabFiller(Form):
    def __init__(self, parent=None):
        Form.__init__(self, parent)

    def TabButtonClicked(self):
        print("Tab button pressed.")

    def LineEditChanged(self):
        print("LineEdit contents edited in tab page!")


class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

    tab_filler = [] # create empty list for tab contents
    tab_page = [] # create empty list for tab page
    tab_count = 0

    def CreateNewTab(self):
        tab_title = "New Tab : " + str(self.tab_count)
        self.tab_filler.append(TabFiller())
        self.tab_filler[self.tab_count].label.setText(tab_title)
        self.tab_page.append(self.tab_filler[self.tab_count])
        self.tabWidget.addTab(self.tab_page[self.tab_count], tab_title)
        self.tab_count += 1

    def MainButtonPressed(self):
        self.CreateNewTab()

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

MainWindow contains a QTabWidget, which is a Button. clicked() signal has been defined in QtDesigner to be sent to the MainButtonPressed() function inside the MainWindow class.

Form widget also created in QTdesigner. Used to fill additional Tab Pages. This contains a Button widget, and a LineEdit Widget.

The Question

I can't get my head around how I can tell which widget has been clicked or edited in each tab.

I know that each Tab Page is stored in the list called tab_page.

Within the MainWindow class, how would I receive a clicked() or finishedEditing() signal for a given widget in a currently active tab?

A Solution

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4 import QtGui
from example_Ui import Ui_MainWindow
from filler_Ui import Form

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

    tab_index = 1 # 1 because we already made a default tab in QtDesigner

    def LineEditChanged(self):
        findWidget = self.tabWidget.widget(self.tabWidget.currentIndex()).findChildren(QtGui.QLineEdit, "lineEdit")
        if findWidget[0].isModified() == True:
            print("LineEdit contents edited in tab page!")
            print("Name of page edited :", "'", self.tabWidget.tabText(self.tabWidget.currentIndex()),"'")

    def TabButtonPressed(self):
        print("YOU DID IT!")
        print("Current Tab Index = ", self.tabWidget.currentIndex())

    def CreateNewTab(self, tabNum):
        tab_title = "New Tab : " + str(self.tab_index)
        self.tabWidget.addTab(Form(), tab_title)

    def MainButtonPressed(self):
        self.CreateNewTab(self.tab_index)
        findWidget = self.tabWidget.widget(self.tab_index).findChildren(QtGui.QPushButton, "tabButton")
        findWidget[0].clicked.connect(self.TabButtonPressed)
        findWidget = self.tabWidget.widget(self.tab_index).findChildren(QtGui.QLineEdit, "lineEdit")
        findWidget[0].editingFinished.connect(self.LineEditChanged)
        self.tab_index += 1

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

Using this there's no need for storing each tab page object in a list. You basically use the QTabWidget to index your pages, and off you go.

If anyone has a more elegant way than this, please inform ;)

War es hilfreich?

Lösung

As outlined in my edited question, I did find the solution to this, which is to use the QTabWidget to "index" each dynamically created tab page.

In QtDesigner I created a main window with one QTabWidget and one button thusly; enter image description here

Here's the object tree for that;

enter image description here

NOTE: I added a signal/slot for the "Click Me!" button in QtDesigner, so that when that button is clicked, the MainButtonPressed function is called.

To fill the tab pages, I also created a Form in QtDesigner, with a button and a QLineEdit widget; enter image description here

And the object tree for that;

enter image description here

I'll reproduce the code here. NOTE: I've now updated this answer to use findChild rather than findChildren above:

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4 import QtGui
from example_Ui import Ui_MainWindow
from filler_Ui import Form

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

    tab_index = 1 # 1 because we already made a default tab in QtDesigner

    def LineEditChanged(self):
        findWidget = self.tabWidget.widget(self.tabWidget.currentIndex()).findChild(QtGui.QLineEdit, "lineEdit")
        if findWidget.isModified() == True:
            print("LineEdit contents edited in tab page!")
        print("Name of page edited :", "'", self.tabWidget.tabText(self.tabWidget.currentIndex()),"'")

    def TabButtonPressed(self):
        print("YOU DID IT!")
        print("Current Tab Index = ", self.tabWidget.currentIndex())

    def CreateNewTab(self, tabNum):
        tab_title = "New Tab : " + str(self.tab_index)
        self.tabWidget.addTab(Form(), tab_title)

    def MainButtonPressed(self):
        self.CreateNewTab(self.tab_index)
        findWidget = self.tabWidget.widget(self.tab_index).findChild(QtGui.QPushButton, "tabButton")
        findWidget.clicked.connect(self.TabButtonPressed)
        findWidget = self.tabWidget.widget(self.tab_index).findChild(QtGui.QLineEdit, "lineEdit")
        findWidget.editingFinished.connect(self.LineEditChanged)
        self.tab_index += 1

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

When run, pressing the "Click Me!" button on the main tab page creates a new tab, and adds the contents of the "filler" page to it.

The variable tab_index keeps track of how many tabs there are and allows you to reference the contents of each tab.

To find a widget in a tab, you use the findChild function of Qt;

findWidget = self.tabWidget.widget(self.tab_index).findChild(QtGui.QPushButton, "tabButton")

Finding a specific widget is straightforward. You specify the type of widget you're looking for (QtGui.QPushButton) , and the name you assigned it in QtDesigner (tabButton)

In this case the found widget can be referenced by the variable findWidget.

You can then connect signals to function slots as usual;

findWidget.clicked.connect(self.TabButtonPressed)

In this case I used the new-style signal connection method to connect the clicked() signal to a function named TabButtonPressed in my program.

Rinse and repeat for each widget on the Tab Page you wish to do something with.

After that, it really is plain sailing ;)

I hope this information helps others in their GUI endeavours. You can probably use the same technique with the QToolBox widget.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top