In the following code, I'm hiding non-selected items in a QListWidget. (self.field is an
instance of QListWidget).
# Make selected items visible and other items hidden:
for i in range(self.field.count()):
self.field.item(i).setHidden(not self.field.item(i).isSelected())
When I hide non-selected items, they are essentially whited out, i.e., the space does not close up (see below). Is there any way to close up the whitespace?
Here is an example of a list widget with a dynamic height. This is achieved by subclassing QListWidget and overriding viewportSizeHint and minimumSizeHint. The size adjust policy is set to AdjustToContents so that the list widget will update its size when its contents have changed. The horizontal scroll bar is set to ScrollBarAlwaysOff to avoid the extra vertical space added at the bottom of the list widget that is reserved for the horizontal scroll bar if it were to be shown.
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import Qt
class ListWidget(QtWidgets.QListWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
def minimumSizeHint(self) -> QtCore.QSize:
return QtCore.QSize(-1, -1)
def viewportSizeHint(self) -> QtCore.QSize:
if self.model().rowCount() == 0:
return QtCore.QSize(self.width(), 0)
height = sum(self.sizeHintForRow(i) for i in range(self.count()) if not self.item(i).isHidden())
width = super().viewportSizeHint().width()
return QtCore.QSize(width, height)
class Widget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
# create and populate ListWidget instance
self.list_widget = ListWidget()
self.list_widget.setSelectionMode(QtWidgets.QListWidget.MultiSelection)
self.list_widget.addItems('Aardvark Bear Cat Donkey Echidna Ferret Goose'.split())
# setup rest of gui
self.select_button = QtWidgets.QPushButton('Select')
self.clear_button = QtWidgets.QPushButton('Clear selection')
vlayout = QtWidgets.QVBoxLayout(self)
vlayout.addWidget(QtWidgets.QLabel('Choose your mascots'))
vlayout.addWidget(self.list_widget)
# stretch added to layout to accommodate for varying height of list widget
vlayout.addStretch(1)
hlayout = QtWidgets.QHBoxLayout()
hlayout.addWidget(self.select_button)
hlayout.addWidget(self.clear_button)
self.select_button.setDefault(True)
vlayout.addLayout(hlayout)
self.select_button.clicked.connect(self.select)
self.clear_button.clicked.connect(self.clear_selection)
def select(self):
for i in range(self.list_widget.count()):
self.list_widget.item(i).setHidden(not self.list_widget.item(i).isSelected())
def clear_selection(self):
self.list_widget.clearSelection()
for i in range(self.list_widget.count()):
self.list_widget.item(i).setHidden(False)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
win = Widget()
win.show()
app.exec()
Screenshot:
Related
I'm trying to create a compound widget similiar to the following:
A Rectangle overlayed with a button that is partially outside the rectangle's bounds.
Here is the code corresponding to that image:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QPoint
from PyQt5.QtGui import QResizeEvent
class MyWidget(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.layout = QHBoxLayout()
self.layout.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.layout)
self.lbl = QLabel()
self.lbl.setStyleSheet('background: #EE6622')
self.lbl.setFixedSize(125, 150)
self.layout.addWidget(self.lbl)
self.btn = QPushButton(parent=self)
self.btn.setStyleSheet('background: #ABCDEF')
self.btn.setFixedSize(25, 25)
def resizeEvent(self, event: QResizeEvent) -> None:
super().resizeEvent(event)
self.update_btn_pos()
def update_btn_pos(self):
pos = (
self.lbl.pos() +
QPoint(
self.lbl.rect().width() - int(self.btn.width() / 2),
-int(self.btn.height() / 2))
)
self.btn.move(pos)
if __name__ == "__main__":
a = QApplication(sys.argv)
window = MyWidget()
window.show()
a.exec()
My problem is that the widget's behaviour when resizing suggests that the button is not really "part of" that widget - it is cut-off as if it weren't there:
I tried to overwrite the sizeHint()-method to include the button, but that only solves the problem on startup, I can still resize the window manually to cut the button off again.
What must be changed in order to make this work?
I think I might have found a solution myself by adding the following to the __init__ - method:
self.layout.setContentsMargins(
0,
int(self.btn.height() / 2),
int(self.btn.width() / 2),
0
)
By setting the contentsMargin, the size of the big rectangle doesn't change because it is fixed and the parent widget still covers the space under the button:
I'm not sure if this is the *right way* to do it though ...
Alright, thanks to #musicamante this is the final code:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QResizeEvent
class MyWidget(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.layout = QHBoxLayout()
self.setLayout(self.layout)
self.lbl = QLabel()
self.lbl.setStyleSheet('background: #EE6622')
self.lbl.setFixedSize(125, 150)
self.layout.addWidget(self.lbl)
self.btn = QPushButton(parent=self)
self.btn.setStyleSheet('background: #ABCDEF')
self.btn.setFixedSize(25, 25)
# set contents margin of layout to half the button's size
self.layout.setContentsMargins(
*([int(self.btn.height() / 2), int(self.btn.width() / 2)]*2)
)
def resizeEvent(self, event: QResizeEvent) -> None:
super().resizeEvent(event)
self.update_btn_pos()
def update_btn_pos(self):
rect = self.btn.rect()
rect.moveCenter(self.lbl.geometry().topRight())
self.btn.move(rect.topLeft())
if __name__ == "__main__":
a = QApplication(sys.argv)
window = MyWidget()
window.show()
a.exec()
Result:
On paint event widget paints itself and all of his children clipped to his bounds. You can try to set button parent to MyWidget's parent, but you'll still have problem of button blocking part of some other widget or clipping on window's client area.
On the other hand there is no much difference between hovering button thats inside parent's widget and hovering button that sticks out, messing with other widgets.
In reference to this answer on adding a new tab button to QTabWidget,
I am unsure where the QPushButton is added to the QTabBar.
I assume the setParent method on the pushButton adds it to the tab bar.
But when I try to implement it, the pushButton doesnt seem to appear anywhere on the tab bar even if I add hard values to the move operation.
Here is a minimum reproducible example,
from PyQt5 import QtGui, QtCore, QtWidgets
class TabBarPlus(QtWidgets.QTabBar):
"""Tab bar that has a plus button floating to the right of the tabs."""
plusClicked = QtCore.pyqtSignal()
def __init__(self):
super().__init__()
# Plus Button
self.plusButton = QtWidgets.QPushButton("+")
self.plusButton.setParent(self)
self.plusButton.setFixedSize(20, 20) # Small Fixed size
self.plusButton.clicked.connect(self.plusClicked.emit)
self.movePlusButton() # Move to the correct location
# end Constructor
def sizeHint(self):
"""Return the size of the TabBar with increased width for the plus button."""
sizeHint = QtWidgets.QTabBar.sizeHint(self)
width = sizeHint.width()
height = sizeHint.height()
return QtCore.QSize(width+25, height)
# end tabSizeHint
def resizeEvent(self, event):
"""Resize the widget and make sure the plus button is in the correct location."""
super().resizeEvent(event)
self.movePlusButton()
# end resizeEvent
def tabLayoutChange(self):
"""This virtual handler is called whenever the tab layout changes.
If anything changes make sure the plus button is in the correct location.
"""
super().tabLayoutChange()
self.movePlusButton()
# end tabLayoutChange
def movePlusButton(self):
"""Move the plus button to the correct location."""
# Find the width of all of the tabs
size = sum([self.tabRect(i).width() for i in range(self.count())])
# size = 0
# for i in range(self.count()):
# size += self.tabRect(i).width()
# Set the plus button location in a visible area
h = self.geometry().top()
w = self.width()
if size > w: # Show just to the left of the scroll buttons
self.plusButton.move(w-54, h)
else:
self.plusButton.move(size, h)
# end movePlusButton
# end class MyClass
class CustomTabWidget(QtWidgets.QTabWidget):
"""Tab Widget that that can have new tabs easily added to it."""
def __init__(self, parent=None):
super().__init__(parent)
# Tab Bar
self.tab = TabBarPlus()
self.setTabBar(self.tab)
# Properties
self.setMovable(True)
self.setTabsClosable(True)
# Signals
self.tab.plusClicked.connect(self.addTab)
# self.tab.tabMoved.connect(self.moveTab)
# self.tabCloseRequested.connect(self.removeTab)
# end Constructor
# end class CustomTabWidget
class AppDemo(QtWidgets.QMainWindow):
def __init__(self):
super(AppDemo, self).__init__()
self.centralwidget = QtWidgets.QWidget(self)
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setContentsMargins(0, -1, 0, -1)
self.playlist_manager = CustomTabWidget(self.centralwidget)
self.horizontalLayout.addWidget(self.playlist_manager)
blankWidget = QtWidgets.QWidget(self.playlist_manager)
self.playlist_manager.addTab(blankWidget, "New")
self.setCentralWidget(self.centralwidget)
self.show()
# end class AppDemo
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
w = AppDemo()
w.setWindowTitle('AppDemo')
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Expected behvaiour is that a "+" button appears at the right of all the tabs,
but no such button appears.
Okay so after some brainstorming, I figured the issue out. Unlike PyQt4. The QTabBar width does not span the entire width of the QTabWidget, and as such the PlusButton when moved to the right of all the tabs will exceed the width of the parent widget and disappear.
The Solution to this is to add the QPushButton in the QTabWidget itself and emit layoutchange from the QTabBar.
Here is a working example, I have modified values to fit my use case
class tabBarPlus(QTabBar):
layoutChanged = pyqtSignal()
def resizeEvent(self, event):
super().resizeEvent(event)
self.layoutChanged.emit()
def tabLayoutChange(self):
super().tabLayoutChange()
self.layoutChanged.emit()
class customTabWidget(QTabWidget):
plusClicked = pyqtSignal()
def __init__(self, parent=None):
super(customTabWidget, self).__init__(parent)
self.tab = tabBarPlus()
self.setTabBar(self.tab)
self.plusButton = QPushButton('+', self)
self.plusButton.setFixedSize(35, 25)
self.plusButton.clicked.connect(self.plusClicked.emit)
self.setMovable(True)
self.setTabsClosable(True)
self.tab.layoutChanged.connect(self.movePlusButton)
def movePlusButton(self):
size = sum([self.tab.tabRect(i).width() for i in range(self.tab.count())])
h = max(self.tab.geometry().bottom() - 24, 0)
w = self.tab.width()
print(size, w, h)
if size > w:
self.plusButton.move(w-self.plusButton.width(), h)
else:
self.plusButton.move(size-2, h)
I'm having though time figuring out what kind of signal is emitted in following situation:
Basicly that's QScrollArea that holds multiple QTableWidgets:
class ScrollArea(QtGui.QScrollArea):
def __init__(self):
super(ScrollArea, self).__init__()
self.scroll_widget = QtGui.QWidget()
self.scroll_layout = QtGui.QVBoxLayout()
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setWidgetResizable(True)
self.__create_content()
self.setWidget(self._content_widget)
self.scroll_layout.addWidget(self)
self.scroll_widget.setLayout(self.scroll_layout)
def __create_content(self):
self._content_widget = QtGui.QWidget()
self._content_widget_layout = QtGui.QVBoxLayout()
self._content_widget.setLayout(self._content_widget_layout)
def add_item(self, item):
self._content_widget_layout.addWidget(item)
I'm using Plastique style for QApplication. As it can be seen from the above picture, when an item is clicked inside QScrollArea, blue border appears. What I would like to know is which signal is emitted when the border is drawn? I need this information so I can append a row to the selected QTableWidget whenever a button (on the left side) is clicked.
Also you can see that there is a 'x' inside each table, when 'x' is pressed that QTableWidget gets removed from QScrollArea. If there is a solution for previous problem, I could also remove QTableWidget depending on user selection rather than user clicking the 'x'.
To get the widget that has the focus you can use the focusChanged signal of QApplication:
from PyQt4 import QtCore, QtGui
class HorizontalHeader(QtGui.QHeaderView):
def __init__(self, parent=None):
super(HorizontalHeader, self).__init__(QtCore.Qt.Horizontal, parent)
self.button = QtGui.QToolButton(self, text="x")
self.sectionResized.connect(self.handleSectionResized)
def handleSectionResized(self):
last_ix = self.count() - 1
pos = QtCore.QPoint(self.sectionViewportPosition(last_ix) + self.sectionSize(last_ix) , 0)
self.button.move(pos)
def showEvent(self, event):
self.handleSectionResized()
super(HorizontalHeader, self).showEvent(event)
class TableView(QtGui.QTableView):
def __init__(self, *args, **kwargs):
super(TableView, self).__init__(*args, **kwargs)
header = HorizontalHeader(self)
header.button.clicked.connect(self.deleteLater)
self.setHorizontalHeader(header)
QtGui.qApp.focusChanged.connect(self.onFocusChanged)
def onFocusChanged(self, old, new):
if new == self:
self.deleteLater()
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
scrollArea = QtGui.QScrollArea()
scrollArea.setWidgetResizable(True)
widget = QtGui.QWidget()
scrollArea.setWidget(widget)
lay = QtGui.QVBoxLayout(widget)
for i in range(10):
w = TableView()
model = QtGui.QStandardItemModel(4, 2, w)
w.setModel(model)
lay.addWidget(w)
scrollArea.show()
sys.exit(app.exec_())
I have a QScrollArea containing a widget with a QVBoxLayout. Inside this layout are several other widgets. I want the user to be able to drag the lower borders of those widgets to resize them in the vertical direction. When they are resized, I don't want them to "steal" size from the other widgets in the scrolling area; instead I want the entire scrolled "page" to change its size. So if you enlarge one of the widgets, it should push the other widgets down (out of the viewport of the scroll area); if you shrink it, it should pull the other widgets up. Dragging the border of one widget should not change the size of any of the other widgets in the vertical scroll; it should just move them.
I began by using a QSplitter. If I use that, I can drag to change the size of a widget, but there doesn't seem to be a way to get it to "push/pull" the others as I described above, rather than growing/shrinking them. But I can't find any other way to give a widget a draggable handle that will allow me to change its size. How can I accomplish this?
Here is a simple example of what I'm doing. (In this example I've commented out the splitter, but if you uncomment it you can see what happens with that version.)
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.Qsci import QsciScintilla, QsciLexerPython
class SimplePythonEditor(QsciScintilla):
def __init__(self, parent=None):
super(SimplePythonEditor, self).__init__(parent)
self.setMinimumHeight(50)
class Chunk(QFrame):
def __init__(self, parent=None):
super(Chunk, self).__init__(parent)
layout = QVBoxLayout(self)
sash = QSplitter(self)
layout.addWidget(sash)
sash.setOrientation(Qt.Vertical)
editor = self.editor = SimplePythonEditor()
output = self.output = SimplePythonEditor()
output.setReadOnly(True)
sash.addWidget(editor)
sash.addWidget(output)
self.setLayout(layout)
print(self.sizePolicy())
class Widget(QWidget):
def __init__(self, parent= None):
global inout
super(Widget, self).__init__()
#Container Widget
widget = QWidget()
#Layout of Container Widget
layout = QVBoxLayout(self)
#sash = QSplitter(self)
#layout.addWidget(sash)
#sash.setOrientation(Qt.Vertical)
for num in range(5):
editor = SimplePythonEditor()
editor.setText("Some stuff {}".format(num))
layout.addWidget(editor)
#sash.addWidget(editor)
widget.setLayout(layout)
#Scroll Area Properties
scroll = QScrollArea()
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll.setWidgetResizable(True)
scroll.setWidget(widget)
scroll.setMaximumHeight(500)
#Scroll Area Layer add
vLayout = QVBoxLayout(self)
vLayout.addWidget(scroll)
self.setLayout(vLayout)
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = Widget()
dialog.show()
app.exec_()
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowTitle("MainWindow")
MainWindow.resize(500, 500)
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
MainWindow.setCentralWidget(self.centralwidget)
QMetaObject.connectSlotsByName(MainWindow)
class Ewindow(QMainWindow,QApplication):
"""docstring for App"""
resized = pyqtSignal()
def __init__(self,parent):
super(Ewindow,self).__init__(parent=parent)
self.setGeometry(500, 500, 800,800)
self.setWindowTitle('Mocker')
self.setWindowIcon(QIcon('icon.png'))
self.setAttribute(Qt.WA_DeleteOnClose)
ui2 = Ui_MainWindow()
ui2.setupUi(self)
self.resized.connect(self.readjust)
def resizeEvent(self, event):
self.resized.emit()
return super(Ewindow, self).resizeEvent(event)
def readjust(self):
self.examForm.move(self.width()-self.examForm.width(),0)
self.btn_skip.move(self.width()-self.btn_skip.width(),self.height()-100)
self.btn_next.move(self.btn_showAnswers.x()+self.btn_showAnswers.width(),self.height()-100)
self.btn_prev.move(0,self.height()-100)
self.btn_showAnswers.move(self.btn_prev.x()+self.btn_prev.width(),self.height()-100)
self.btn_home.move(self.width()-200,self.height()-150)
self.lbscreen1.resize(self.width()-self.examForm.width(),self.height()-200)
self.examForm.resize(200,self.height()-150)
self.btn_skip.resize(self.examForm.width(),100)
self.btn_next.resize(self.btn_prev.width(),100)
self.btn_prev.resize(self.width()*0.25,100)
self.btn_showAnswers.resize(self.btn_prev.width(),100)
self.btn_home.resize(200,50)
here is an example code of a resizable window it moves and stretches widgets as you resize the window. The idea is to keep widget coordinates and sizes relative to each other.
so i had to make a class Ui_MainWindow and set it for my window class ui2.setupUi(self) and also declare the resized = pyqtSignal() which i'd be using to run the readjust function which resets size and coordinates of the widgets like so self.resized.connect(self.readjust).
i hope this helps!
I am trying to set up a window that has a text input & a combo box. At the moment I just want to see the text & the selection displayed under the appropriate widget.
I have used QVBoxLayout() as I will be adding more stuff later & thought it would be a simple way of laying out the window.
Unfortunately only the combo box ever gets displayed. The code:
from PyQt4 import QtCore, QtGui
import sys
class Polyhedra(QtGui.QMainWindow):
def __init__(self):
super(Polyhedra, self).__init__()
self.initUI()
def initUI(self):
# Poly names
self.pNames = QtGui.QLabel(self)
polyNameInput = QtGui.QLineEdit(self)
# polyName entry
polyNameInput.textChanged[str].connect(self.onChanged)
# Polytype selection
self.defaultPolyType = QtGui.QLabel("Random polyhedra", self)
polyType = QtGui.QComboBox(self)
polyType.addItem("Random polyhedra")
polyType.addItem("Spheres")
polyType.addItem("Waterman polyhedra")
polyType.activated[str].connect(self.onActivated)
# Layout
vbox = QtGui.QVBoxLayout()
vbox.addWidget(polyNameInput)
vbox.addWidget(self.pNames)
vbox.addWidget(polyType)
vbox.addWidget(self.defaultPolyType)
vbox.addStretch()
# Set up window
self.setGeometry(500, 500, 300, 300)
self.setWindowTitle('Pyticle')
self.show()
# Combo box
def onActivated(self, text):
self.defaultPolyType.setText(text)
self.defaultPolyType.adjustSize()
# Poly names
def onChanged(self, text):
self.pNames.setText(text)
self.pNames.adjustSize()
def main():
app = QtGui.QApplication(sys.argv)
ex = Polyhedra()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
So whats going on here? Am I missing some important directive to QVBoxLayout()?
Using Python 2.7 on Win 7 x64 machine with PyQt 4.
EDIT: Additional problem (still related to missing widgets)
I have amended the code following the clarification below. I then added more widgets when a certain option in the combobox is chosen (see below) but these widgets dont show. I attempted to add a child widget to 'widget' called 'ranPolyWidget' to take a numerical input.
# Combo box
def onActivated(self, text):
if text=="Random polyhedra":
self.randomSeedLbl = QtGui.QLabel("Seed: ", self)
randomSeed = QtGui.QLineEdit(self)
randomSeed.textChanged[str].connect(self.setSeed)
ranPolyWidget = QtGui.QWidget(self.widget)
rbox = QtGui.QVBoxLayout(ranPolyWidget)
rbox.addWidget(randomSeed)
self.layout().addWidget(ranPolyWidget)
self.show()
else:
self.defaultPolyType.setText(text)
self.defaultPolyType.adjustSize()
Same issue as before, no widgets. I am missing something pretty fundamental arent I?
You're forgetting to set it to the widget or main window, so since the QComboBox is the last one made, it's the only one displayed. Basically, everything is added to the layout, but the layout is "free-floating", and so it does not display properly. You need to bind the layout to a QWidget, which I do here. For most widgets, you can can do this by the QtGui.QVBoxLayout(widget) or by widget.setLayout(layout).
Alternatively, if you want multiple layouts on a widget, you can do have a parent layout and then add each child layout to the main layout.
EDIT: This is a better answer:
Make a widget, set layout to widget and set as central widget.
QMainWindow-s don't like you using the builtin layout or overriding it.
widget = QtGui.QWidget()
vbox = QtGui.QVBoxLayout(widget)
self.setCentralWidget(widget)
Old Answer:
self.layout().addLayout(vbox).
This should fix your issue:
Changes I made:
Since QMainWindow already has a layout, add in a widget (28G) and then set the VBoxLayout to the widget and add it to the main window.
from PyQt4 import QtCore, QtGui
import sys
class Polyhedra(QtGui.QMainWindow):
def __init__(self):
super(Polyhedra, self).__init__()
self.initUI()
def initUI(self):
# Poly names
self.pNames = QtGui.QLabel(self)
polyNameInput = QtGui.QLineEdit(self)
# polyName entry
polyNameInput.textChanged[str].connect(self.onChanged)
# Polytype selection
self.defaultPolyType = QtGui.QLabel("Random polyhedra", self)
polyType = QtGui.QComboBox(self)
polyType.addItem("Random polyhedra")
polyType.addItem("Spheres")
polyType.addItem("Waterman polyhedra")
polyType.activated[str].connect(self.onActivated)
# Layout
widget = QtGui.QWidget()
vbox = QtGui.QVBoxLayout(widget)
vbox.addWidget(polyNameInput)
vbox.addWidget(self.pNames)
vbox.addWidget(polyType)
vbox.addWidget(self.defaultPolyType)
vbox.addStretch()
# Set up window
self.setGeometry(500, 500, 300, 300)
self.setWindowTitle('Pyticle')
self.layout().addWidget(widget)
self.show()
# Combo box
def onActivated(self, text):
self.defaultPolyType.setText(text)
self.defaultPolyType.adjustSize()
# Poly names
def onChanged(self, text):
self.pNames.setText(text)
self.pNames.adjustSize()
def main():
app = QtGui.QApplication(sys.argv)
ex = Polyhedra()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
EDIT:
For adding new widgets, you should add them to the layout of the central widget and parent them to that widget.
Here's how I'd restructure your full code:
from PyQt4 import QtCore, QtGui
import sys
class CentralWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(CentralWidget, self).__init__(parent)
# set layouts
self.layout = QtGui.QVBoxLayout(self)
# Poly names
self.pNames = QtGui.QLabel(self)
polyNameInput = QtGui.QLineEdit(self)
# polyName entry
polyNameInput.textChanged[str].connect(self.onChanged)
# Polytype selection
self.defaultPolyType = QtGui.QLabel("Random polyhedra", self)
polyType = QtGui.QComboBox(self)
polyType.addItem("Random polyhedra")
polyType.addItem("Spheres")
polyType.addItem("Waterman polyhedra")
polyType.activated[str].connect(self.onActivated)
self.layout.addWidget(polyNameInput)
self.layout.addWidget(self.pNames)
self.layout.addWidget(polyType)
self.layout.addWidget(self.defaultPolyType)
self.layout.addStretch()
def onActivated(self, text):
'''Adds randSeed to layout'''
if text=="Random polyhedra":
self.randomSeedLbl = QtGui.QLabel("Seed: ", self)
randomSeed = QtGui.QLineEdit(self)
randomSeed.textChanged[str].connect(self.setSeed)
self.layout.addWidget(randomSeed)
else:
self.defaultPolyType.setText(text)
self.defaultPolyType.adjustSize()
# Poly names
def onChanged(self, text):
self.pNames.setText(text)
self.pNames.adjustSize()
class Polyhedra(QtGui.QMainWindow):
def __init__(self):
super(Polyhedra, self).__init__()
# I like having class attributes bound in __init__
# Not very Qt of me, but it's more
# so I break everything down into subclasses
# find it more Pythonic and easier to debug: parent->child
# is easy when I need to repaint or delete child widgets
self.central_widget = CentralWidget(self)
self.setCentralWidget(self.central_widget)
# Set up window
self.setGeometry(500, 500, 300, 300)
self.setWindowTitle('Pyticle')
self.show()
# Combo box
def onActivated(self, text):
'''Pass to child'''
self.central_widget.onActivated(text)
def main():
app = QtGui.QApplication(sys.argv)
ex = Polyhedra()
sys.exit(app.exec_())
if __name__ == '__main__':
main()