PyQt Rowspan Issues - python

I'm working on creating a GUI for an Irish Dictionary searcher using PyQt. I have already completed it in tkinter, but heard that PyQt was just much better and the way to go, so I wanted to work on a version of it, too. I'm almost done, except I'm having an issue. I'm creating a bilingual version, Irish and English, but I want both versions to use the same text widget, so you can see words you've called in either version. However, it wouldn't show up in the second one, even having it added to the rid, so I had to remove/add it in my switch callback. However, after I did that, it's not showing up the correct size, despite multiple settings on rowspan. The relevant code is attached. The grid that appears at startup in the EnglishVersion class works perfectly (though it'd be nice if I could make it a bit bigger since a lot of text is getting presented), but after I switch versions it becomes too small to be useful.
Edit: New code containing only the problem, as requested
import sys
from PyQt4 import QtGui, QtCore
class Callback():
def remove():
foo.hide()
bar.show()
foo.layout().removeWidget(foo.text_entry)
bar.layout().addWidget(bar.text_entry, 1, 0, 24, 2)
class Text(QtGui.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.text_entry = QtGui.QTextEdit(parent)
class Foo(QtGui.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.text_entry = text.text_entry
self.button = QtGui.QPushButton("Remove and readd text")
self.button.clicked.connect(lambda: Callback.remove())
grid = QtGui.QGridLayout()
grid.addWidget(self.button, 0, 0, 1, 2)
grid.addWidget(self.text_entry, 1, 0, 24, 2)
self.setLayout(grid)
class Bar(QtGui.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.text_entry = text.text_entry
self.button = QtGui.QPushButton("After it has been pushed")
grid = QtGui.QGridLayout()
grid.addWidget(self.button, 0, 0, 1, 2)
self.setLayout(grid)
app = QtGui.QApplication(sys.argv)
text = Text()
foo = Foo()
bar = Bar()
foo.show()
app.exec_()

Related

How to save selected element from combobox as variable in PyQt5?

I'm interested in how to save a selected value from my combobox as variable, so when I press e.g. B then I want it to be saved as SelectedValueCBox = selected value, which would be B in this case.
Thank you for your help
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = "PyQt5 - StockWindow"
self.left = 0
self.top = 0
self.width = 200
self.height = 300
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.tab_widget = MyTabWidget(self)
self.setCentralWidget(self.tab_widget)
self.show()
class MyTabWidget(QWidget):
def __init__(self, parent):
super(QWidget, self).__init__(parent)
self.layout = QVBoxLayout(self)
#self.layout = QGridLayout(self)
self.tabs = QTabWidget()
self.tab1 = QWidget()
self.tabs.resize(300, 200)
self.tabs.addTab(self.tab1, "Stock-Picker")
self.tab1.layout = QGridLayout(self)
button = QToolButton()
self.tab1.layout.addWidget(button, 1,1,1,1)
d = {'AEX':['A','B','C'], 'ATX':['D','E','F'], 'BEL20':['G','H','I'], 'BIST100':['J','K','L']}
def callback_factory(k, v):
return lambda: button.setText('{0}_{1}'.format(k, v))
menu = QMenu()
self.tab1.layout.addWidget(menu, 1,1,1,1)
for k, vals in d.items():
sub_menu = menu.addMenu(k)
for v in vals:
action = sub_menu.addAction(str(v))
action.triggered.connect(callback_factory(k, v))
button.setMenu(menu)
self.tab1.setLayout(self.tab1.layout)
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Since you're already returning a lambda for the connection, the solution is to use a function instead.
class MyTabWidget(QWidget):
def __init__(self, parent):
# ...
def callback_factory(k, v):
def func():
self.selectedValueCBox = v
button.setText('{0}_{1}'.format(k, v))
return func
# ...
self.selectedValueCBox = None
Note that your code also has many issues.
First of all, you should not add the menu to the layout: not only it doesn't make any sense (the menu should pop up, while adding it to a layout makes it "embed" into the widget, and that's not good), but it also creates graphical issues especially because you added the menu to the same grid "slot" (1, 1, 1, 1) which is already occupied by the button.
Creating a layout with a widget as argument automatically sets the layout to that widget. While in your case it doesn't create a big issue (since you've already set the layout) you should not create self.tab1.layout with self. Also, since you've already set the QVBoxLayout (due to the parent argument), there's no need to call setLayout() again.
A widget container makes sense if you're actually going to add more than one widget. You're only adding a QTabWidget to its layout, so it's almost useless, and you should just subclass from QTabWidget instead.
Calling resize on a widget that is going to be added on a layout is useless, as the layout will take care of the resizing and the previous resize call will be completely ignored. resize() makes only sense for top level widgets (windows) or the rare case of widgets not managed by a layout.
self.layout() is an existing property of all QWidgets, you should not overwrite it. The same with self.width() and self.height() you used in the App class.
App should refer to an application class, but you're using it for a QMainWindow. They are radically different types of classes.
Finally, you have no combobox in your code. A combobox is widget that is completely different from a drop down menu like the one you're using. I suggest you to be more careful with the terminology in the future, otherwise your question would result very confusing, preventing people to actually being able to help you.

Force QTabBar tabs to stay as small as possible and ignore sizeHint

I'm trying to have a + button added to a QTabBar. There's a great solution from years ago, with a slight issue that it doesn't work with PySide2. The problem is caused by the tabs auto resizing to fill the sizeHint, which in this case isn't wanted as the extra space is needed. Is there a way I can disable this behaviour?
I've tried QTabBar.setExpanding(False), but according to this answer, the property is mostly ignored:
The bad news is that QTabWidget effectively ignores that property, because it always forces its tabs to be the minimum size (even if you set your own tab-bar).
The difference being in PySide2, it forces the tabs to be the preferred size, where I'd like the old behaviour of minimum size.
Edit: Example with minimal code. The sizeHint width stretches the tab across the full width, whereas in older Qt versions it doesn't do that. I can't really override tabSizeHint since I don't know what the original tab size should be.
import sys
from PySide2 import QtCore, QtWidgets
class TabBar(QtWidgets.QTabBar):
def sizeHint(self):
return QtCore.QSize(100000, super().sizeHint().height())
class Test(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Test, self).__init__(parent)
layout = QtWidgets.QVBoxLayout()
self.setLayout(layout)
tabWidget = QtWidgets.QTabWidget()
tabWidget.setTabBar(TabBar())
layout.addWidget(tabWidget)
tabWidget.addTab(QtWidgets.QWidget(), 'this shouldnt be stretched')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
test = Test()
test.show()
sys.exit(app.exec_())
I think there may be an easy solution to your problem (see below). Where the linked partial solution calculated absolute positioning for the '+' button, the real intent with Qt is always to let the layout engine do it's thing rather than trying to tell it specific sizes and positions. QTabWidget is basically a pre-built amalgamation of layouts and widgets, and sometimes you just have to skip the pre-built and build your own.
example of building a custom TabWidget with extra things across the TabBar:
import sys
from PySide2 import QtWidgets
from random import randint
class TabWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
#layout for entire widget
vbox = QtWidgets.QVBoxLayout(self)
#top bar:
hbox = QtWidgets.QHBoxLayout()
vbox.addLayout(hbox)
self.tab_bar = QtWidgets.QTabBar()
self.tab_bar.setMovable(True)
hbox.addWidget(self.tab_bar)
spacer = QtWidgets.QSpacerItem(0,0,QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
hbox.addSpacerItem(spacer)
add_tab = QtWidgets.QPushButton('+')
hbox.addWidget(add_tab)
#tab content area:
self.widget_stack = QtWidgets.QStackedLayout()
vbox.addLayout(self.widget_stack)
self.widgets = {}
#connect events
add_tab.clicked.connect(self.add_tab)
self.tab_bar.currentChanged.connect(self.currentChanged)
def add_tab(self):
tab_text = 'tab' + str(randint(0,100))
tab_index = self.tab_bar.addTab(tab_text)
widget = QtWidgets.QLabel(tab_text)
self.tab_bar.setTabData(tab_index, widget)
self.widget_stack.addWidget(widget)
self.tab_bar.setCurrentIndex(tab_index)
def currentChanged(self, i):
if i >= 0:
self.widget_stack.setCurrentWidget(self.tab_bar.tabData(i))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
test = TabWidget()
test.show()
sys.exit(app.exec_())
All that said, I think the pre-built QTabWidget.setCornerWidget may be exactly what you're looking for (set a QPushButton to the upper-right widget). The example I wrote should much easier to customize, but also much more effort to re-implement all the same functionality. You will have to re-implement some of the signal logic to create / delete / select / rearrange tabs on your own. I only demonstrated simple implementation, which probably isn't bulletproof to all situations.
Using the code from Aaron as a base to start on, I managed to implement all the functionality required to work with my existing script:
from PySide2 import QtCore, QtWidgets
class TabBar(QtWidgets.QTabBar):
def minimumSizeHint(self):
"""Allow the tab bar to shrink as much as needed."""
minimumSizeHint = super(TabBar, self).minimumSizeHint()
return QtCore.QSize(0, minimumSizeHint.height())
class TabWidgetPlus(QtWidgets.QWidget):
tabOpenRequested = QtCore.Signal()
tabCountChanged = QtCore.Signal(int)
def __init__(self, parent=None):
self._addingTab = False
super(TabWidgetPlus, self).__init__(parent=parent)
# Main layout
layout = QtWidgets.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
# Bar layout
self._tabBarLayout = QtWidgets.QHBoxLayout()
self._tabBarLayout.setContentsMargins(0, 0, 0, 0)
self._tabBarLayout.setSpacing(0)
layout.addLayout(self._tabBarLayout)
self._tabBar = TabBar()
self._tabBarLayout.addWidget(self._tabBar)
for method in (
'isMovable', 'setMovable',
'tabsClosable', 'setTabsClosable',
'tabIcon', 'setTabIcon',
'tabText', 'setTabText',
'currentIndex', 'setCurrentIndex',
'currentChanged', 'tabCloseRequested',
):
setattr(self, method, getattr(self._tabBar, method))
self._plusButton = QtWidgets.QPushButton('+')
self._tabBarLayout.addWidget(self._plusButton) # TODO: Find location to insert
self._plusButton.setFixedWidth(20)
self._tabBarLayout.addStretch()
# Content area
self._contentArea = QtWidgets.QStackedLayout()
layout.addLayout(self._contentArea)
# Signals
self.currentChanged.connect(self._currentChanged)
self._plusButton.clicked.connect(self.tabOpenRequested.emit)
# Final setup
self.installEventFilter(self)
#QtCore.Slot(int)
def _currentChanged(self, i):
"""Update the widget."""
if i >= 0 and not self._addingTab:
self._contentArea.setCurrentWidget(self.tabBar().tabData(i))
def eventFilter(self, obj, event):
"""Intercept events until the correct height is set."""
if event.type() == QtCore.QEvent.Show:
self.plusButton().setFixedHeight(self._tabBar.geometry().height())
self.removeEventFilter(self)
return False
def tabBarLayout(self):
return self._tabBarLayout
def tabBar(self):
return self._tabBar
def plusButton(self):
return self._plusButton
def tabAt(self, point):
"""Get the tab at a given point.
This takes any layout margins into account.
"""
offset = self.layout().contentsMargins().top() + self.tabBarLayout().contentsMargins().top()
return self.tabBar().tabAt(point - QtCore.QPoint(0, offset))
def addTab(self, widget, name=''):
"""Add a new tab.
Returns:
Tab index as an int.
"""
self._addingTab = True
tabBar = self.tabBar()
try:
index = tabBar.addTab(name)
tabBar.setTabData(index, widget)
self._contentArea.addWidget(widget)
finally:
self._addingTab = False
return index
def insertTab(self, index, widget, name=''):
"""Inserts a new tab.
If index is out of range, a new tab is appended.
Returns:
Tab index as an int.
"""
self._addingTab = True
tabBar = self.tabBar()
try:
index = tabBar.insertTab(index, name)
tabBar.setTabData(index, widget)
self._contentArea.insertWidget(index, widget)
finally:
self._addingTab = False
return index
def removeTab(self, index):
"""Remove a tab."""
tabBar = self.tabBar()
self._contentArea.removeWidget(tabBar.tabData(index))
tabBar.removeTab(index)
if __name__ == '__main__':
import sys
import random
app = QtWidgets.QApplication(sys.argv)
test = TabWidgetPlus()
test.addTab(QtWidgets.QPushButton(), 'yeah')
test.insertTab(0, QtWidgets.QCheckBox(), 'what')
test.insertTab(1, QtWidgets.QRadioButton(), 'no')
test.removeTab(1)
test.setMovable(True)
test.setTabsClosable(True)
def tabTest():
name = 'Tab ' + str(random.randint(0, 100))
index = test.addTab(QtWidgets.QLabel(name), name)
test.setCurrentIndex(index)
test.tabOpenRequested.connect(tabTest)
test.tabCloseRequested.connect(lambda index: test.removeTab(index))
test.show()
sys.exit(app.exec_())
The one difference is if you're using tabWidget.tabBar().tabAt(point), this is no longer guaranteed to be correct as it doesn't take any margins into account. I set the margins to 0 so this shouldn't be an issue, but I also included those corrections in TabWidgetPlus.tabAt.
I only copied a few methods from QTabBar to QTabWidget as some may need extra testing.

How to prevent window and widgets in a pyqt5 application from changing size when the visibility of one widget is altered

I want to create a dialog, in which the user should first select one item in a drop down, and for some choices specify an additional parameter. For the sake of the example let's say that the possible choices are A and B and for B the user has to enter a text. The text field should not be visible when A is selected.
Here is a MWE:
#!/usr/bin/env python
import sys
from PyQt5.QtWidgets import QApplication, QComboBox, QDialog, QGridLayout, QLineEdit
class Example(QDialog) :
def __init__(self, parent=None) :
super(QDialog, self).__init__(parent)
self.mainLayout = QGridLayout()
self.setLayout(self.mainLayout)
self.comboBox = QComboBox()
self.comboBox.addItems(['A', 'B'])
self.mainLayout.addWidget(self.comboBox, 0, 0)
self.lineEdit = QLineEdit('')
self.lineEdit.setMinimumWidth(50)
self.mainLayout.addWidget(self.lineEdit, 0, 1)
self.comboBox.activated[str].connect(self.update)
self.update(str(self.comboBox.currentText()))
def update(self, choice) :
if 'B' in choice :
self.lineEdit.setVisible(True)
else :
self.lineEdit.setVisible(False)
if __name__ == '__main__':
app = QApplication(sys.argv)
example = Example()
example.show()
sys.exit(app.exec_())
The problem is, that when initially choice A is presented, the size of the dialog is just enough for the comboBox. When option B is selected, the window is expanded and everything is as it should be. However, when option A is selected again, the comboBox' width increases, taking up all of the avalaible space, instead of leaving empty space to the right.
How can I have space allocated for the text field, no matter if visible or not? What am I missing here?
EDIT The answer by S.Nick solves the problem of the MWE in a way, but not the way I was hoping for: As soon as the scenario is more complex, widgets get reallocated again, e.g. if a QLabel is added in front of the comboBox
self.label = QLabel('label')
self.mainLayout.addWidget(self.label, 0, 0)
self.comboBox = QComboBox()
self.comboBox.addItems(['A', 'B'])
self.mainLayout.addWidget(self.comboBox, 0, 1, alignment=Qt.AlignLeft)
self.lineEdit = QLineEdit('', self)
self.lineEdit.setMinimumWidth(50)
self.mainLayout.addWidget(self.lineEdit, 0, 2)
then the comboBox is flipped around when changing the selection. What I want is that, once in the beginning space and position is allocated for each widget and that the space and position is permanent no matter if any widget is visible or not.
You could try something like this:
def __init__(self, parent=None) :
super(QDialog, self).__init__(parent)
self.mainLayout = QGridLayout()
self.setLayout(self.mainLayout)
self.label = QLabel('label')
self.mainLayout.addWidget(self.label, 0, 0)
self.comboBox = QComboBox()
self.comboBox.addItems(['A', 'B'])
self.mainLayout.addWidget(self.comboBox, 0, 1)
self.lineEdit = QLineEdit('', self)
self.lineEdit.setMinimumWidth(200)
self.mainLayout.addWidget(self.lineEdit, 0, 2)
self.comboBox.activated[str].connect(self.update)
self.mainLayout.setColumnStretch(2,1)
self.adjustSize()
self.update(str(self.comboBox.currentText()))
self.mainLayout.setColumnStretch(2,1) will make sure that the last column will take up all the extra horizontal space even when the line edit widget is hidden.
self.adjustSize() adjusts the size of the main window to the sum of the sizes of all its child widgets. Since at this point the line edit widget is still visible, its size is taken into account as well when the size of the main window is adjusted.
Screenshots
Initial window:
After selecting B:

QPalette for beginners - where to start

I recently made my first python and PyQt program and now I'm looking to play with colors to make it look good. I've been looking around the documentation and the QPalette documentation seems to suggest that a QPalette is the way to go as opposed to manually setting the colors for each widget. Problem is I can't find a whole lot of info out there on how to use this in practice and while there is certainly a lot of data in the documentation for a beginner like me it is lacking in many examples!
From what I understand my goal here is to establish within a QPalette object the sort of "global" colors for my app, and then I assign that palette to all of my widgets right? So what is the best way to go about this? For example I want to set all of my buttons to a dark gray background. Looking at the documentation it seems you need to set the QPalette.button() color using .setColor but I'm not able to get this to work (see line #83). But I was able to set the background color of the dialog specifically just above that.
Here's just the Gui part of my code:
import sys
from PyQt4 import QtGui, QtCore
class BatchTable(QtGui.QTableWidget):
def __init__(self, parent):
super(BatchTable, self).__init__(parent)
self.setAcceptDrops(True)
self.setColumnCount(5)
self.setColumnWidth(1,50)
self.hideColumn(1)
self.hideColumn(3)
self.hideColumn(4)
self.horizontalHeader().setStretchLastSection(True)
self.setHorizontalHeaderLabels(QtCore.QString("Status;Alpha;File;Full Path;Process ID").split(";"))
class ffmpegBatch(QtGui.QWidget):
def __init__(self):
super(ffmpegBatch, self).__init__()
self.initUI()
def initUI(self):
self.pBar = QtGui.QProgressBar()
self.edit = QtGui.QTextEdit()
cmdGroup = QtGui.QGroupBox("Commandline arguments")
self.alphaCheck = QtGui.QCheckBox("Output alpha as separate file")
fpsLbl = QtGui.QLabel("FPS:")
self.fpsCombo = QtGui.QComboBox()
self.fpsCombo.addItem("29.97")
self.fpsCombo.addItem("23.976")
hbox1 = QtGui.QHBoxLayout()
hbox1.addWidget(self.alphaCheck)
hbox1.addWidget(fpsLbl)
hbox1.addWidget(self.fpsCombo)
cmdGroup.setLayout(hbox1)
saveGroup = QtGui.QGroupBox("Output")
saveLocationBox = QtGui.QHBoxLayout()
self.outputLocation = QtGui.QLineEdit()
self.popBtn = QtGui.QPushButton("Pop dir")
saveLocationBox.addWidget(self.outputLocation)
saveLocationBox.addWidget(self.popBtn)
saveBtnsBox = QtGui.QHBoxLayout()
pasteFromClipboard = QtGui.QPushButton("Paste from clipboard")
upOneBtn = QtGui.QPushButton("./")
upTwoBtn = QtGui.QPushButton("././")
saveBtnsBox.addWidget(pasteFromClipboard)
saveBtnsBox.addWidget(upOneBtn)
saveBtnsBox.addWidget(upTwoBtn)
saveMasterBox = QtGui.QVBoxLayout()
saveMasterBox.addLayout(saveLocationBox)
saveMasterBox.addLayout(saveBtnsBox)
saveGroup.setLayout(saveMasterBox)
self.runBtn = QtGui.QPushButton("Run Batch Transcode")
showDebugger = QtGui.QPushButton("Show debugger")
showDebugger.setCheckable(True)
self.mainBox = QtGui.QVBoxLayout()
self.table = BatchTable(self)
self.mainBox.addWidget(self.table)
self.mainBox.addWidget(cmdGroup)
self.mainBox.addWidget(saveGroup)
self.mainBox.addWidget(self.runBtn)
self.mainBox.addWidget(self.pBar)
self.mainBox.addWidget(showDebugger)
self.mainBox.addWidget(self.edit)
self.edit.hide()
self.setLayout(self.mainBox)
self.setGeometry(300, 300, 600, 700)
self.setWindowTitle('FFMPEG Batch Converter')
# make pretty
palette = QtGui.QPalette()
palette.setColor(self.backgroundRole(), QtGui.QColor(40, 40, 40))
self.setPalette(palette)
palette.setColor(palette.button(), QtGui.QColor(100, 100, 100))
self.runBtn.setPalette(palette)
def main():
app = QtGui.QApplication(sys.argv)
ex = ffmpegBatch()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Never mind, looks like stylesheets with cascading are a way better way to go. For example to set all buttons within the application to an absolutely beautiful yellow color: QApplication.setStyleSheet("QPushButton { background: yellow }")

Interpreting simple code to python code

I build a lot of very basic QT repetitive programs at work with QT python then compile them with py2exe. These are used by my coworkers at controllers for another program. I am wonder how I could build a python interpreter that would convert simple commands into actual python code similar to the way Processing converts a simplified code into java.
For example the "simple code" file may read:
slider('Distance', 'dist', 50, 100, 'int')
button('Apply Changes', 'apply')
which I would then interpret into a pyQT program form using types below:
slider(label, name, min, max, type)
button(label, name)
These would all be written to new python file, which when run would generate the appropriate form. The part I am stuck on is how to interpret the "simple code" into python code.
Thanks in advance
Solution #1
The code below is uses the regex and split idea by SPEN-zar to identify the widget type, then parse the inputs to generate the necessary outputs. Obviously, this will be expanded upon to generate real pyQT file, but this is the basic demonstrates the basic logic.
Thank you for the help.
import re
input = ["slider('Distance', 'dist', 50, 100, 'int')", "button('Apply Changes', 'apply')"]
pattern = r"([a-z]+)\s*\((.*)\)"
rexp = re.compile(pattern)
for line in input:
content = rexp.findall(line)
if content[0][0] == 'slider':
params = content[0][1].split(',')
name = params[0]
label = params[1]
minimum = float(params[2])
maximum = float(params[3])
print 'Slider Type: name-%s, label-%s, min-%f, max-%f' % (name, label, minimum, maximum)
elif content[0][0] == 'button':
params = content[0][1].split(',')
name = params[0]
label = params[1]
print 'Button Type: name-%s, label-%s' % (name, label)
else:
print 'This widget type is not recognized'
Solution #2
After doing further research into blender's suggestion, I have modified the code below that uses a class to define a button. This class can then be easily added to the form as many times as needed. By building classes for all the types needed it would be easy to easy generate forms as well maintain and add to the library.
from PyQt4 import QtGui, QtCore
import sys
class Main(QtGui.QMainWindow):
def __init__(self, parent = None):
super(Main, self).__init__(parent)
# main button
self.addButton = QtGui.QPushButton('button to add other widgets')
self.addButton.clicked.connect(self.addWidget)
# scroll area widget contents - layout
self.scrollLayout = QtGui.QFormLayout()
# scroll area widget contents
self.scrollWidget = QtGui.QWidget()
self.scrollWidget.setLayout(self.scrollLayout)
# scroll area
self.scrollArea = QtGui.QScrollArea()
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setWidget(self.scrollWidget)
# main layout
self.mainLayout = QtGui.QVBoxLayout()
# add all main to the main vLayout
self.mainLayout.addWidget(self.addButton)
self.mainLayout.addWidget(self.scrollArea)
# central widget
self.centralWidget = QtGui.QWidget()
self.centralWidget.setLayout(self.mainLayout)
# set central widget
self.setCentralWidget(self.centralWidget)
def addButton(self):
self.scrollLayout.addRow(Test())
class Test(QtGui.QWidget):
def __init__( self, parent=None):
super(Test, self).__init__(parent)
self.pushButton = QtGui.QPushButton('I am in Test widget')
self.pushButton.clicked.connect(self.testPush)
layout = QtGui.QHBoxLayout()
layout.addWidget(self.pushButton)
self.setLayout(layout)
def testPush(self):
print "The test button was pushed!"
app = QtGui.QApplication(sys.argv)
myWidget = Main()
for i in xrange(5):
myWidget.addButton()
myWidget.show()
app.exec_()
Have you tried just parsing it into a .ui format? That is XML, which is pretty straightforward.
Whichever output format you prefer, try PLY for the lexing and parsing. Otherwise, just use a regular expression to search for the substring with "(" ")" surrounding it and use .split(',') to get the arguments. That's my take.

Categories

Resources