Can I make a groupbox outside of a scroll area? - python

I have a QGroupBox with a title '123'. Inside the QGroupBox, there should be a QScrollArea. That means that the title '123' of QGrouBox should be outside of the QScrollArea.
My sample codes are as below.
import sys
import PyQt4
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Example(QWidget):
def __init__(self, parent = None):
super().__init__()
btn = QPushButton('button')
scroll = QScrollArea()
scroll.setWidgetResizable(True)
scroll.setWidget(btn)
groupbox = QGroupBox('123')
groupbox.setLayout(scroll)
self.show()
def main():
app = QApplication(sys.argv)
main = Example()
main.show()
sys.exit(app.exec_())
As you can see above, now it returns TypeError: setLayout(self, QLayout): argument 1 has unexpected type 'QScrollArea'.
I'm just wondering if this is achievable? Thanks!!

When you want to add the content to a QGroupBox you must do through a layout that contains the necessary widgets, in this case as it is only a widget we can use any layout, and in this layout we add the widget that this case is the QScrollArea as sample then:
class Example(QWidget):
def __init__(self, parent = None):
super().__init__()
self.setLayout(QVBoxLayout())
btn = QPushButton('button')
scroll = QScrollArea()
scroll.setWidgetResizable(True)
scroll.setWidget(btn)
groupbox = QGroupBox('123', self)
groupbox.setLayout(QVBoxLayout())
groupbox.layout().addWidget(scroll)
self.layout().addWidget(groupbox)
Screenshot:

Related

How can I get rid of the previous layout and set new Grid Layout in QMainWindow?

I am a newbie with PyQt. I am trying to organize my buttons on a grid layout, but I guess the window has a default layout already. How can I get rid of it and replace it with the new Grid Layout? I have contained the code block relevant with hashes ###, Here is my program:
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import QWidget
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QWidget.__init__(self)
self.setMinimumSize (800,600) # set minimum size for window
self.setWindowTitle("CoolPlay Kabul") # set window title
self.setWindowIcon(QtGui.QIcon("images/CoolPlay.png"))# set icon for Window
myMenu = self.menuBar()
File_Menu = myMenu.addMenu("&File")
Items_Menu = myMenu.addMenu("&Items")
Playlist_Menu = myMenu.addMenu("&Playlist")
Option_Menu = myMenu.addMenu("&Option")
Exit_Menu = myMenu.addMenu("&Exit")
File_Menu.addAction("New Time")
File_Menu.addAction("Delete Time")
File_Menu.addSeparator()
File_Menu.addAction("Exit")
Items_Menu.addAction("New Item")
Items_Menu.addAction("Delete Item")
Items_Menu.addSeparator()
Items_Menu.addAction("Toggle Segue")
Playlist_Menu.addAction("Clear Playlist")
Playlist_Menu.addAction("Save playlist")
Playlist_Menu.addAction("Load Playlist")
Playlist_Menu.addSeparator()
Playlist_Menu.addAction("Clear 'Played' Indication")
Option_Menu.addAction("Application Setup")
Exit_Menu.addAction("Help")
Exit_Menu.addAction("About")
######################################################
Overall_Layout = QtGui.QGridLayout(self)
self.setLayout(Overall_Layout)
Play_Button = QtGui.QPushButton(QtGui.QIcon("images/PLAY.bmp"), "PLAY",self)
Overall_Layout.addWidget(Play_Button,1,2)
Overall_Layout.addWidget(Play_Button,2,2)
########################################################
self.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
CoolPlay = MainWindow()
CoolPlay.show()
sys.exit(app.exec_())
QMainWindow is a special widget since it already has a preset layout as shown below:
So in this case you should not set a layout to the QMainWindow but to the central widget, but first establish a centralwidget, using the indicated thing we get the following:
######################################################
central_widget = QtGui.QWidget()
self.setCentralWidget(central_widget)
Overall_Layout = QtGui.QGridLayout(central_widget)
Play_Button = QtGui.QPushButton(QtGui.QIcon("images/PLAY.bmp"), "PLAY")
Overall_Layout.addWidget(Play_Button,1,2)
Overall_Layout.addWidget(Play_Button,2,2)
########################################################
On the other hand if you inherit from QMainWindow you must call the QMainWindow constructor, but in code you call QWidget, so you must modify it to:
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Or
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()

Python PyQt4: Single child window

I have a simple PyQt4 example.
When run, it displays a QMainWindow with a button.
If you click the button, then a second QMainWindow is created.
If you click it again, you get 2 second windows.
What is an elegant and simple way to prevent more than 1 second window in this example?
import sys
from PyQt4.QtGui import *
class win2(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self,parent)
layout = QVBoxLayout()
label = QLabel(self)
label.setText('This is win2')
layout.addWidget(label)
self.adjustSize()
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
layout = QVBoxLayout()
button1 = QPushButton("win2", self)
layout.addWidget(button1)
button1.clicked.connect(self.showwin2)
def showwin2(self):
w2 = win2(self)
w2.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
Your Function creates a new instance of the class win2 each time the button is pressed. To Supress this behavior only call the show and raise_ functions instead of creating a new instance.
I would create the class as follows, and only use the button to 'show' the window. Tested and works as intended. Also consider using self when assigning your variables so they can be accessed throughout the class instance.
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
layout = QVBoxLayout()
button1 = QPushButton("win2", self)
layout.addWidget(button1)
button1.clicked.connect(self.showwin2)
self.w2 = win2(self)
def showwin2(self):
self.w2.show()
self.w2.raise_()

Widget on corner QTabBar is not in corner

I have a pushbutton to add a tab in a QTabWidget. But when I change the button's size, it's not in the corner anymore. So how can I bring it to the corner like in the first picture?
Not change size:
Change size:
Here is my code:
from PyQt4 import QtGui, QtCore
class PlaylistTable(QtGui.QWidget):
def __init__(self):
super(PlaylistTable, self).__init__()
self.playlistTable = QtGui.QTableWidget(self)
self.playlistTable.setFrameShape(QtGui.QFrame.NoFrame)
self.playlistTable.setFrameShadow(QtGui.QFrame.Sunken)
self.playlistTable.setLineWidth(0)
self.playlistTable.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.playlistTable.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
self.playlistTable.setHorizontalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
self.playlistTable.setShowGrid(True)
self.playlistTable.setGridStyle(QtCore.Qt.SolidLine)
self.playlistTable.setWordWrap(True)
self.playlistTable.setCornerButtonEnabled(True)
self.playlistTable.verticalHeader().setVisible(False)
class CustomTabWidget(QtGui.QTabWidget):
"""Tab Widget that that can have new tabs easily added to it."""
def __init__(self, parent=None):
super(CustomTabWidget, self).__init__(parent)
# QtGui.QTabWidget.__init__(self, parent)
# Tab Bar
self.tab = QtGui.QTabBar()
self.setTabBar(self.tab)
# Properties
self.setMovable(True)
self.setTabsClosable(True)
self.plusButton = QtGui.QPushButton("+")
self.plusButton.setFixedSize(QtCore.QSize(22, 22))
self.setCornerWidget(self.plusButton)
# Signals
self.connect(self.plusButton, QtCore.SIGNAL('clicked()'), self.addTab)
# self.tab.plusClicked.connect(self.addTab)
self.tab.tabMoved.connect(self.tab.moveTab)
self.tabCloseRequested.connect(self.removeTab)
def addTab(self):
string = QtCore.QString.fromUtf8("Playlist")
tab = PlaylistTable()
super(CustomTabWidget, self).addTab(tab, string)
class AppDemo(QtGui.QMainWindow):
def __init__(self):
super(AppDemo, self).__init__()
self.centralwidget = QtGui.QWidget(self)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setContentsMargins(0, -1, 0, -1)
self.playlist_manager = CustomTabWidget(self.centralwidget)
self.horizontalLayout.addWidget(self.playlist_manager)
self.playlist_manager.addTab()
self.setCentralWidget(self.centralwidget)
self.show()
# end class AppDemo
def main():
import sys
app = QtGui.QApplication(sys.argv)
w = AppDemo()
w.setWindowTitle('AppDemo')
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I'm guessing the reason is this, from QTabWidget Documentation:
The geometry of the widget is determined
based on the widget's sizeHint() and the style().
If you print the sizeHint() of the QPushButton you will see that width never goes below a certain value.
I've found an alternative is to use a QToolButton which can do everything (even more) a QPushButton does.
self.plusButton = QtGui.QToolButton(self)
self.plusButton.setText("+")

PyQt add widget to second window

I've got the following python code which opens a second window. I can't figure out how to add a label or pushbutton to this second window. I thought it would be easy but nothing I try seems to work. Thanks!
from PyQt4 import QtGui, QtCore
class Window(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
menu = self.menuBar().addMenu(self.tr('View'))
action = menu.addAction(self.tr('New Window'))
action.triggered.connect(self.handleNewWindow)
def handleNewWindow(self):
window = QtGui.QMainWindow(self)
window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
window.setWindowTitle(self.tr('New Window'))
window.show()
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.resize(300, 300)
window.show()
sys.exit(app.exec_())
If the two windows are different, it makes more sense to create two class.
I guess the second one doesn't need to be a QMainWindow (= it doesn't need a menu and a toolbar and a status bar etc), so let's just make it a QWidget.
class SecondWindow(QtGui.QWidget):
def __init__(self,parent):
QtGui.QWidget.__init__(self,parent)
self.button=QtGui.QPushButton("my button !")
layout=QtGui.QHBoxLayout()
layout.addWidget(self.button)
self.setLayout(layout)
self.show()
In your main window, you cretae and instance of the class SecondWindow:
class FirstWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
...
self.show()
def handleNewWindow(self):
self.childWindow = SecondWindow(self)
If you just want a TopLevel window, using QtGui.QDialog seems to be more appropriate. To add button and label, you can do something like this:
def handleNewWindow(self):
window = QtGui.QMainWindow(self)
window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
window.setWindowTitle(self.tr('New Window'))
button = QtGui.QPushButton("MY BUTTON!") #create button
label = QtGui.QLabel("MY LABEL!") # create label
CentralWidget = QtGui.QWidget() # create an empty widget
CentralWidgetLayout = QtGui.QHBoxLayout() # create a layout
CentralWidgetLayout.addWidget(label) # add your label to the layout
CentralWidgetLayout.addWidget(button) # add your button to the layout
CentralWidget.setLayout(CentralWidgetLayout) # assign your layout to the empty widget
window.setCentralWidget(CentralWidget) #make the assigned widget CentralWidget
window.show()

Delete space between Combobox and label (QGridlayout)

I'm trying to create a Application form by PySide, and i follow some tutorial , but i have a problem that is a space between QLabel and QCombobox.
This is my code
import sys
from PySide import QtCore, QtGui
from PySide.QtGui import *
from PySide.QtCore import *
class Window(QtGui.QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.setMinimumHeight(660)
self.setMinimumWidth(700)
self.setMaximumHeight(660)
self.setMaximumWidth(900)
grid = QtGui.QGridLayout()
grid.addWidget(self.First(), 0,0,2,0)
self.setLayout(grid)
self.setWindowTitle("Library")
self.resize(700, 660)
def First(self):
groupBox = QtGui.QFrame()
groupBox.setMaximumWidth(230)
groupBox.setMaximumHeight(700)
lbFile = QtGui.QLabel("File :",self)
lbFolders = QtGui.QLabel("Folders :",self)
cbFile = QtGui.QComboBox(self)
cbFile.addItem("File 1")
cbFile.addItem("File 2")
lvFolders = QtGui.QListView(self)
lvFolders.setMaximumWidth(220)
lvFolders.setMaximumHeight(500)
vbox = QtGui.QGridLayout()
vbox.addWidget(lbFile,0,0)
vbox.addWidget(cbFile,0,1)
vbox.addWidget(lbFolders,2,0)
vbox.addWidget(lvFolders,3,0,1,2)
groupBox.setLayout(vbox)
return groupBox
app = QApplication.instance()
if app is None:
app = QApplication(sys.argv)
clock = Window()
clock.show()
app.exec_()
and this is my Form :
I dont know how to delete the space between QLabel "File" and QCombobox "File 1"
Adjust the stretch factor for the second column of the layout, and possibly also make the folders label span both columns:
vbox = QtGui.QGridLayout()
vbox.addWidget(lbFile,0,0)
vbox.addWidget(cbFile,0,1)
vbox.addWidget(lbFolders,2,0,1,2)
vbox.addWidget(lvFolders,3,0,1,2)
vbox.setColumnStretch(1, 1)

Categories