How to hide the Horizontal box using pyqt4 - python

Here in my sample program i want to hide the hbox.but i couldn't find any method to hide hbox in pyqt4.Can any one please help me how to hide the horizontal box.Thank you in advance.
Given below is my code:
import sys
from PyQt4 import QtGui
global payments
payments = False
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.grid = QtGui.QGridLayout()
self.hbox = QtGui.QHBoxLayout()
self.cash = QtGui.QPushButton("cash")
self.card = QtGui.QPushButton("card")
self.wallet = QtGui.QPushButton("wallet")
self.hbox.addWidget(self.cash)
self.hbox.addWidget(self.card)
self.hbox.addWidget(self.wallet)
self.paybtn = QtGui.QPushButton("pay")
self.paybtn.clicked.connect(self.show_payments)
self.grid.addWidget(self.paybtn,1,0)
self.setLayout(self.grid)
self.setGeometry(300, 300, 500,500)
self.show()
def show_payments(self):
global payments
payments = not payments
print payments
if payments:
self.paybtn.setText('Edit Order')
self.grid.addLayout(self.hbox,0,0)
else:
self.paybtn.setText('Pay')
#here i want to hide the self.hbox
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

The function of the layouts is to manage the positions and sizes of other widgets, your task is not to hide. Instead you must create a widget where the hbox is with the buttons and that widget set it in the grid layout, so it is only necessary to hide or show the new widget.
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 500,500)
grid = QtGui.QGridLayout(self)
self.foo_widget = QtGui.QWidget(visible=False)
self.foo_widget.setSizePolicy(QtGui.QSizePolicy.Preferred,
QtGui.QSizePolicy.Maximum)
hbox = QtGui.QHBoxLayout(self.foo_widget)
hbox.setContentsMargins(0, 0, 0, 0)
self.cash = QtGui.QPushButton("cash")
self.card = QtGui.QPushButton("card")
self.wallet = QtGui.QPushButton("wallet")
hbox.addWidget(self.cash)
hbox.addWidget(self.card)
hbox.addWidget(self.wallet)
self.paybtn = QtGui.QPushButton("Pay", clicked=self.show_payments)
grid.addWidget(self.foo_widget, 0, 0)
grid.addWidget(self.paybtn, 1, 0)
def show_payments(self):
global payments
payments = not payments
self.paybtn.setText('Edit Order' if payments else 'Pay')
self.foo_widget.setVisible(payments)

Related

How do I add table to central widget in PyQt5 keeping my menu bar?

I am having trouble creating a PyQt5 GUI where I want a table of information as the central widget and a menu bar (which I will eventually put sorting options into). My code allows me to have either the table OR the menu but not both, and can't set a central widget because the class is not defined. Hopefully it's just something small I'm missing. Would appreciate any help, thanks.
Here is my code:
class Main(QMainWindow):
def __init__(self,parent = None):
super().__init__()
#self.grid_widget = App(grid)
self.initUI()
def initUI(self):
exitAct = QAction(QIcon('exit.png'), '&Exit', self)
exitAct.setShortcut('Ctrl+Q')
exitAct.setStatusTip('Exit application')
exitAct.triggered.connect(qApp.quit)
self.statusBar()
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAct)
#self.setCentralWidget(self.grid_widget)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Main()
sys.exit(app.exec_())
class App(QWidget):
def __init__(self, parent = None):
super(App, self).__init__(parent)
self.title = 'PyQt5 table'
self.left = 90
self.top = 90
self.width = 800
self.height = 600
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.createTable()
# Add layout, add table to grid layout
grid = QGridLayout()
grid.addWidget(self.tableWidget)
self.setLayout(grid)
# Show widget
self.show()
def createTable(self):
# Create table
self.tableWidget = QTableWidget()
self.tableWidget.setRowCount(len(q1.index))
self.tableWidget.setColumnCount(len(q1.columns))
self.tableWidget.setHorizontalHeaderLabels(heads) #set column names to headers in df
for i in range(len(q1.index)):
for j in range(len(q1.columns)):
self.tableWidget.setItem(i, j, QTableWidgetItem(str(q1.iat[i, j])))
self.tableWidget.resizeColumnsToContents()
self.tableWidget.resizeRowsToContents()
self.tableWidget.move(0,0)
# table selection change
self.tableWidget.doubleClicked.connect(self.on_click)
#pyqtSlot()
def on_click(self):
print("\n")
for currentQTableWidgetItem in self.tableWidget.selectedItems():
print(currentQTableWidgetItem.row(), currentQTableWidgetItem.column(), currentQTableWidgetItem.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Which produces this:
and ignores my whole tablewidget altogether.
I have commented out the 3rd line in the QMainWindow because it produces an error saying that App is not defined.
How do I set the central widget so that it allows the table to appear as well? Thanks.
the application should only have a single main, to have several only the first one will be executed, and therefore everything that you are after will not be defined, and consequently App is not defined as you indicate.
So the solution is to eliminate the intermediate main and copy it to the final main.
class Main(QMainWindow):
def __init__(self,parent = None):
super().__init__()
self.grid_widget = App(self)
self.initUI()
...
class App(QWidget):
...
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Main()
sys.exit(app.exec_())

PySide switching widgets with events?

I can't figure it. I want to be able to swap out QWidgets according to events like button clicks but I am missing something and I haven't been able to search out any example along the lines of the code below. What I want to do is click one of the top buttons and get the widget below to switch between either the QCalendar or QtextEdit. Where am I going wrong?
Thanks!
#!/usr/bin/python
import sys
from PySide import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QtGui.QHBoxLayout(self)
widget = QtGui.QCalendarWidget()
button1 = QtGui.QPushButton('Calendar', self)
button1.setCheckable(True)
button1.clicked[bool].connect(self.setWidget)
button2 = QtGui.QPushButton('TextEdit', self)
button2.setCheckable(True)
button2.clicked[bool].connect(self.setWidget)
splitter1 = QtGui.QSplitter(QtCore.Qt.Vertical)
splitter1.addWidget(button1)
splitter1.addWidget(button2)
splitter1.addWidget(widget)
hbox.addWidget(splitter1)
self.setLayout(hbox)
self.setGeometry(0, 0, 600, 600)
self.setWindowTitle('Switching QWidgets')
self.show()
def setWidget(self, pressed):
source = self.sender()
val1 = QtGui.QCalendarWidget()
val2 = QtGui.QTextEdit()
if source.text() == "Calendar":
widget = val1
QtGui.QWidget.update(Example.hbox)
elif source.text() == "TextEdit":
widget = val2
QtGui.QWidget.update(Example.hbox)
else:
widget = val1
QtGui.QWidget.update(Example.hbox)
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You have to use QStackedWidget, where you update the indexes.
class Example(QtGui.QWidget):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.initUI()
def initUI(self):
hbox = QtGui.QHBoxLayout(self)
self.stacked = QtGui.QStackedWidget(self)
self.stacked.addWidget(QtGui.QCalendarWidget())
self.stacked.addWidget(QtGui.QTextEdit())
splitter1 = QtGui.QSplitter(QtCore.Qt.Vertical)
for text in ["Calendar", "TextEdit"]:
btn = QtGui.QPushButton(text, self)
btn.clicked.connect(self.setWidget)
splitter1.addWidget(btn)
splitter1.addWidget(self.stacked)
hbox.addWidget(splitter1)
self.setLayout(hbox)
self.setGeometry(0, 0, 600, 600)
self.setWindowTitle('Switching QWidgets')
self.show()
def setWidget(self):
source = self.sender()
if source.text() == "Calendar":
self.stacked.setCurrentIndex(0)
elif source.text() == "TextEdit":
self.stacked.setCurrentIndex(1)
If you change your code to keep a reference to the calendar and textedit widgets, then add them both to the splitter in init... You can just use the show and hide functions in your setWidget().
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.hbox = QtGui.QHBoxLayout(self)
self.widget = QtGui.QCalendarWidget()
self.widget2 = QtGui.QTextEdit()
button1 = QtGui.QPushButton('Calendar', self)
button1.setCheckable(True)
button1.clicked[bool].connect(self.setWidget)
button2 = QtGui.QPushButton('TextEdit', self)
button2.setCheckable(True)
button2.clicked[bool].connect(self.setWidget)
splitter1 = QtGui.QSplitter(QtCore.Qt.Vertical)
splitter1.addWidget(button1)
splitter1.addWidget(button2)
splitter1.addWidget(self.widget)
splitter1.addWidget(self.widget2)
self.widget2.hide()
self.hbox.addWidget(splitter1)
self.setLayout(self.hbox)
self.setGeometry(59, 59, 600, 600)
self.setWindowTitle('Switching QWidgets')
self.show()
def setWidget(self, pressed):
source = self.sender()
if source.text() == "Calendar":
self.widget.show()
self.widget2.hide()
elif source.text() == "TextEdit":
self.widget.hide()
self.widget2.show()

Building Qt Gui from few classes together

Below is a short example of my Gui. I am trying to split my Gui in few parts.
The elements of InputAxis should be on the same height (horizontal split) and self.recipient should be below them (vertical split).
In InputAxis I am trying to place a QLineEdit but in my Gui I don't see it.
import sys
from PySide import QtCore
from PySide import QtGui
class InputAxis(object):
def __init__(self):
self.frame = QtGui.QFrame()
self.input_interface = QtGui.QLineEdit()
self.form_layout = QtGui.QFormLayout()
def genAxis(self):
self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
self.form_layout.addRow('&Input:', self.input_interface)
return self.frame
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self, parent = None)
self.layout = QtGui.QVBoxLayout()
self.form_layout = QtGui.QFormLayout()
self.axes = list()
self.axes.append(InputAxis())
self.axes.append(InputAxis())
self.splitter1 = QtGui.QSplitter(QtCore.Qt.Horizontal)
for axis in self.axes:
self.splitter1.addWidget(axis.genAxis())
self.form_layout.addWidget(self.splitter1)
self.setMinimumWidth(400)
self.recipient = QtGui.QLineEdit(self)
# Add it to the form layout with a label
self.form_layout.addRow('&Recipient:', self.recipient)
# Add the form layout to the main VBox layout
self.layout.addLayout(self.form_layout, 0)
# Set the VBox layout as the window's main layout
self.setLayout(self.layout)
QtGui.QApplication.setStyle( QtGui.QStyleFactory.create('Cleanlooks') )
def run(self):
self.show()
def main():
qt_app = QtGui.QApplication(sys.argv)
window = Window()
window.run()
sys.exit(qt_app.exec_())
if __name__=="__main__":
main()
the reason it did not work was this line:
self.form_layout = QtGui.QFormLayout()
It should be:
self.form_layout = QtGui.QFormLayout(self.frame)

splitter in pyside ui now visible

why is the splitter not displaying in the tab?
I'm not entirely sure what is wrong. I'm guessing that the layout box is not resizing to match the size of the tab, in return is producing such a small window in the tab which isn't big enough to display it's contents. Any code suggestions are welcome.
import sys
from PySide import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
# controls - main
# ----------------------------------------------------------------------
main_tabWidget = QtGui.QTabWidget()
# controls - factions tab
# ----------------------------------------------------------------------
factions_tab = QtGui.QWidget()
factions_tab_layout = QtGui.QHBoxLayout()
topleft = QtGui.QFrame(factions_tab)
topleft.setFrameShape(QtGui.QFrame.StyledPanel)
topright = QtGui.QFrame(factions_tab)
topright.setFrameShape(QtGui.QFrame.StyledPanel)
splitter1 = QtGui.QSplitter(QtCore.Qt.Horizontal)
splitter1.addWidget(topleft)
splitter1.addWidget(topright)
factions_tab_layout.addWidget(splitter1)
QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Cleanlooks'))
main_tabWidget.addTab(factions_tab, "Factions")
# main layout
# ----------------------------------------------------------------------
main_layout = QtGui.QVBoxLayout()
main_layout.addWidget(main_tabWidget)
self.setLayout(main_layout)
self.setGeometry(300, 300, 400, 300)
self.setWindowTitle('Example')
self.center()
self.show()
def center(self):
qr = self.frameGeometry()
cp = QtGui.QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def onChanged(self, text):
self.lbl.setText(text)
self.lbl.adjustSize()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The factions_tab_layout is never given a parent, and is not set as a layout on any widget. This means its child widgets will be garbage-collected when initUI returns, because you do not give any of them parents, either.
Minimal fix:
factions_tab_layout = QtGui.QHBoxLayout(factions_tab)

Add widgets on the fly in pyside

Very new to pyside so maybe a stupid question. I want to create a pyside UI which has a variable number of items in it and also has the possibility to add items while it is running and to make it even more complex it also needs a scroll bar to fit it all on screen!
This is what I've got right now:
import sys
from PySide import QtGui
from PySide import QtCore
class example(QtGui.QWidget):
def __init__(self, parent= None):
super(example, self).__init__()
grid = QtGui.QGridLayout()
grid.setSpacing(10)
self.widget = QtGui.QWidget()
self.layout = QtGui.QGridLayout(self)
for i in range(5):
btn = QtGui.QPushButton("test"+str(i))
self.layout.addWidget(btn,i,0)
btn.clicked.connect(self.buttonClicked)
self.count = i
self.widget.setLayout(self.layout)
self.scroll = QtGui.QScrollArea()
self.scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.scroll.setWidget(self.widget)
grid.addWidget(self.scroll,3,0)
self.setLayout(grid)
def buttonClicked(self):
title = QtGui.QLabel('Title'+str(self.count))
self.layout.addWidget(title,self.count + 1,0)
self.count += 1
self.widget.addLayout(self.layout,0)
self.scroll.addWidget(self.widget,0)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
dialog = example()
dialog.show()
sys.exit(app.exec_())
But somehow the layout gets messed up when adding items through one of the buttons.
Does anybody have an idea how to fix this?
Thanx!
You're not far off. The key piece you're missing is QScrollArea.setWidgetResizable, which will ensure the scrollarea automatically resizes its viewport to fit the contents.
I've made some other adjustments to your example and added comments where appropriate:
class example(QtGui.QWidget):
def __init__(self, parent= None):
super(example, self).__init__()
grid = QtGui.QGridLayout()
grid.setSpacing(10)
self.widget = QtGui.QWidget()
# set the widget as parent of its own layout
self.layout = QtGui.QGridLayout(self.widget)
for i in range(5):
btn = QtGui.QPushButton("test"+str(i))
self.layout.addWidget(btn,i,0)
btn.clicked.connect(self.buttonClicked)
# following lines are redundant
# self.count = i
# self.widget.setLayout(self.layout)
self.scroll = QtGui.QScrollArea()
# need this so that scrollarea handles resizing
self.scroll.setWidgetResizable(True)
# these two lines may not be needed now
self.scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.scroll.setWidget(self.widget)
grid.addWidget(self.scroll, 3, 0)
self.setLayout(grid)
def buttonClicked(self):
title = QtGui.QLabel('Title' + str(self.layout.count()))
self.layout.addWidget(title)
# following lines are redundant
# self.layout.addWidget(title, self.count + 1, 0)
# self.count += 1
# self.widget.addLayout(self.layout,0)
# self.scroll.addWidget(self.widget,0)

Categories