I have to align 'Menu5' to the right side of MenuBar.
Is that possible in Python? (PyQt4)
Example
I found information on how to do this in C there
Aligning QMenuBar items (add some on left and some on right side)
But I don't know how I can do this in Python.
My code:
import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
grid = QtGui.QGridLayout()
panel = QtGui.QWidget()
panel.setLayout(grid)
self.setCentralWidget(panel)
menubar1 = self.menuBar()
menubar1.addMenu('&Menu1')
menubar1.addMenu('&Menu2')
menubar1.addMenu('&Menu3')
menubar1.addMenu('&Menu4')
menubar1.addMenu('&Menu5')
self.setLayout(grid)
self.move(300, 150)
self.setWindowTitle('TestApp')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Please help.
QMenuBar has setCornerWidget function which allows you to do that.
menubar1 = self.menuBar()
menubar1.addMenu('&Menu1')
menubar1.addMenu('&Menu2')
menubar1.addMenu('&Menu3')
menubar1.addMenu('&Menu4')
self.menuBr= QtGui.QMenuBar(menubar1)
menubar1.setCornerWidget(self.menuBr, QtCore.Qt.TopRightCorner)
self.menu5 = QtGui.QMenu(self.menuBr)
self.menu5.setTitle("Menu5")
self.menuBr.addAction(self.menu5.menuAction())
Related
I found some code on here that shows an example of how you can get the window to resize when the widget is hidden, and it works for me. Here is the code:
from PyQt4 import QtCore, QtGui
import sys
class MainWindow(QtGui.QWidget):
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
super(MainWindow, self).__init__()
self.button = QtGui.QPushButton('Show/Hide')
self.button.setCheckable(True)
self.frame = QtGui.QFrame()
self.frame.setFixedHeight(100)
self.layout = layout = QtGui.QVBoxLayout()
layout2 = QtGui.QVBoxLayout()
self.setLayout(layout)
self.frame.setLayout(layout2)
layout.addWidget(self.button)
layout.addWidget(self.frame)
layout.addStretch(1)
layout2.addWidget(QtGui.QLabel('Yoyoyo'))
self.button.toggled.connect(self.clickAction)
def startup(self):
self.show()
sys.exit(self.app.exec_())
def clickAction(self):
checked = self.button.isChecked()
if checked:
self.frame.show()
else:
self.frame.hide()
QtCore.QTimer.singleShot(0, self.resizeMe)
def resizeMe(self):
self.resize(self.minimumSizeHint())
if __name__ == "__main__":
myApp = MainWindow()
myApp.startup()
I then tried to modify this to match my existing code by separating the mainWindow class and the widget class. Here is the code that does that.
from PySide import QtGui,QtCore
import sys
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.w = testW(self)
self.setCentralWidget(self.w)
self.show()
class testW(QtGui.QWidget):
def __init__(self,parent):
super(testW,self).__init__()
self.parent = parent
self.button = QtGui.QPushButton('Show/Hide')
self.button.setCheckable(True)
self.button.setChecked(True);
self.frame = QtGui.QFrame()
self.frame.setFixedHeight(100)
self.layout = layout = QtGui.QVBoxLayout()
layout2 = QtGui.QVBoxLayout()
self.setLayout(layout)
self.frame.setLayout(layout2)
layout.addWidget(self.button)
layout.addWidget(self.frame)
layout.addStretch(1)
layout2.addWidget(QtGui.QLabel('Yoyoyo'))
self.button.toggled.connect(self.clickAction)
def clickAction(self):
checked = self.button.isChecked()
if checked:
self.frame.show()
else:
self.frame.hide()
QtCore.QTimer.singleShot(0, self.resizeMe)
def resizeMe(self):
self.resize(self.minimumSizeHint())
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myApp = MainWindow()
sys.exit(app.exec_())
#time.sleep(1)
Running the first code does what I want it to. After I hide the widget, the window resizes to the correct size. The second implementation of the code does not shrink and expand the window when I hide and show the widget. Is this because the MainWindow is in a separate class?
Use size policies for your widgets. For your example you can change UI creation code as follows:
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.w = testW(self)
self.w.setSizePolicy(
QtWidgets.QSizePolicy.MinimumExpanding,
QtWidgets.QSizePolicy.MinimumExpanding
)
self.setCentralWidget(self.w)
self.show()
Please note new setSizePolicy call which say Qt layout engine how to change the size of your widget according to its content.
Unfortunately QMainWindow does not respect sizeHint automatically, but it is calculated properly, so you can adjustSize manually:
def clickAction(self):
checked = self.button.isChecked()
if checked:
self.frame.show()
else:
self.frame.hide()
QtCore.QTimer.singleShot(0, self.parent.adjustSize)
You do not need to resize your widget itself, because it will be resized according to the policy. Even sizeHint will be calculated automatically so you need only to call adjustSize of QMainWindow.
PS: I used PySide2 instead of PySide so the imports are different a little bit:
from PySide2 import QtWidgets, QtCore
a similar question is already answered here: How to center text in QComboBox?
but still I cant find a method how to center the items shown in the list?
from PyQt4 import QtGui, QtCore
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
layout = QtGui.QVBoxLayout(self)
self.combo = QtGui.QComboBox()
self.combo.setEditable(True)
self.combo.lineEdit().setAlignment(QtCore.Qt.AlignCenter)
self.combo.addItems('One Two Three Four Five'.split())
layout.addWidget(self.combo)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
One possible option is to use a delegate:
from PyQt4 import QtGui, QtCore
class AlignDelegate(QtGui.QStyledItemDelegate):
def initStyleOption(self, option, index):
super(AlignDelegate, self).initStyleOption(option, index)
option.displayAlignment = QtCore.Qt.AlignCenter
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
layout = QtGui.QVBoxLayout(self)
self.combo = QtGui.QComboBox()
delegate = AlignDelegate(self.combo)
self.combo.setItemDelegate(delegate)
self.combo.setEditable(True)
self.combo.lineEdit().setAlignment(QtCore.Qt.AlignCenter)
self.combo.addItems('One Two Three Four Five'.split())
layout.addWidget(self.combo)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
I am creating an application where I have a main window whit a label and then a docked widget that is in another file. I want to change the main windows label from a button at the docked widget. I try to import the main window file but then I can not access to the label. And I also tried to call a function in the main windows that changes the label but then the label does not change.
Here is the code:
main_window.py:
import results_window
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.define_main_windows()
self.create_dock_widgets()
def define_main_windows(self):
# Define de Main window properties
self.setMinimumSize(QSize(300, 100))
self.setWindowTitle("Python SkyLibris")
self.setWindowIcon(QtGui.QIcon("skylibris_icon.png"))
self.setStyleSheet("QMainWindow {background: 'white';}")
self.top = 50
self.left = 0
self.width = 1300
self.height = 400
self.setGeometry(self.left, self.top, self.width, self.height)
self.result = QLabel("result:")
self.setCentralWidget(self.result)
def create_dock_widgets(self):
# Create dock widgets
self.results_window = results_window.results_window()
self.resultsWindowDock = QDockWidget("Results Viewer", self)
self.resultsWindowDock.setWidget(self.results_window )
self.resultsWindowDock.setFloating(False)
self.resultsWindowDock.setVisible(True)
self.addDockWidget(Qt.LeftDockWidgetArea, self.resultsWindowDock)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
results_window.py:
import main_window
class results_window(QWidget):
def __init__(self):
super(results_window, self).__init__()
print("init")
self.label = QLabel()
self.value = QLineEdit()
self.bt = QPushButton("Click")
self.bt.clicked.connect(self.clickMethod)
self.main_layout = QVBoxLayout()
self.main_layout.addWidget(self.label)
self.main_layout.addWidget(self.value)
self.main_layout.addWidget(self.bt)
self.setLayout(self.main_layout)
def clickMethod(self):
print(self.value.text())
text = self.value.text()
main_window.result.setText(text)
You are using the wrong tools, for example your code has a circular import that causes your application to close since it is equivalent to a while True.
In Qt, signals and slots are used to share data asynchronously, as well as contributing to the fact that there is no coupling between classes. In your case, Results_Window must have a signal that transmits that information to the MainWindow, this signal must be emit within clickMethod.
results_window.py
from PyQt5 import QtCore, QtWidgets
class Results_Window(QtWidgets.QWidget):
resultChanged = QtCore.pyqtSignal(str)
def __init__(self):
super(Results_Window, self).__init__()
print("init")
self.label = QtWidgets.QLabel()
self.value = QtWidgets.QLineEdit()
self.bt = QtWidgets.QPushButton("Click")
self.bt.clicked.connect(self.clickMethod)
main_layout = QtWidgets.QVBoxLayout(self)
main_layout.addWidget(self.label)
main_layout.addWidget(self.value)
main_layout.addWidget(self.bt)
#QtCore.pyqtSlot()
def clickMethod(self):
text = self.value.text()
self.resultChanged.emit(text)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
w = Results_Window()
w.show()
sys.exit(app.exec_())
main_window.py
from PyQt5 import QtCore, QtGui, QtWidgets
import results_window
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.define_main_windows()
self.create_dock_widgets()
def define_main_windows(self):
self.setMinimumSize(QtCore.QSize(300, 100))
self.setWindowTitle("Python SkyLibris")
self.setWindowIcon(QtGui.QIcon("skylibris_icon.png"))
self.setStyleSheet("QMainWindow {background: 'white';}")
top, left, width, height = 50, 0, 1300, 400
self.setGeometry(left, top, width, height)
self.result = QtWidgets.QLabel("result:")
self.setCentralWidget(self.result)
def create_dock_widgets(self):
self.results_window = results_window.Results_Window()
self.results_window.resultChanged.connect(self.result.setText)
self.resultsWindowDock = QtWidgets.QDockWidget("Results Viewer", self)
self.resultsWindowDock.setWidget(self.results_window )
self.resultsWindowDock.setFloating(False)
self.resultsWindowDock.setVisible(True)
self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.resultsWindowDock)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
I had similar problem in PyQT5 where I was unable to access and set the local variables. After a lot of struggle I found writing to file and reading from file as the best solution. Simply write the desired output to file and access the same info from other file. Works great!
I need to add a new tab, but I am having problems. I want to add new tabs in the main window, and keep the methods of the class Editor(). I can do this without having to create the class Editor() but need it to be so. Sorry for my English.
This is my code:
from PyQt4 import QtGui
from PyQt4 import QtCore
class Main(QtGui.QMainWindow):
def __init__(self):
super(Main, self).__init__()
self.initUi()
def initUi(self):
self.setWindowTitle("Editor")
self.resize(640, 480)
self.edit = Editor()
newAc = QtGui.QAction('New', self)
newAc.setShortcut('Ctrl+N')
newAc.triggered.connect(self.new_)
menu = self.menuBar()
filemenu = menu.addMenu('&File')
filemenu.addAction(newAc)
self.tab = QtGui.QTabWidget(self)
self.setCentralWidget(self.tab)
class Editor(QtGui.QTextEdit):
def __init__(self, parent=None):
super(Editor, self).__init__(parent)
def new_(self):
tab = QtGui.QTextEdit(self.tab)
self.tab.addTab(tab, 'Untitled')
def main():
import sys
app = QtGui.QApplication(sys.argv)
w = Main()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
If you want to have the same text on both (or more) tabs you can use the same Editor class, but if not, you need instantiate an Editor object for each tab.
Also your code have some problems:
1- You are handling the tabs inside Editor objects. Instead, you must handle tabs at Main level.
2- The "default" tab you're adding when you create the Main object do not have any related QTextEdit change:
self.tab = QtGui.QTabWidget(self)
self.setCentralWidget(self.tab) # <---- tab without QTextEdit
add this:
self.tab = QtGui.QTabWidget(self)
self.editor = Editor(self.tab) # editor receives self.tab widget as parent.
self.setCentralWidget(self.tab)
also you will need define Editor class before Main.
3- Main object don't have any method called new_, Editor does. So the line:
newAc.triggered.connect(self.new_)
it's wrong.
So your code might look like:
from PyQt4 import QtGui
from PyQt4 import QtCore
class Editor(QtGui.QTextEdit):
def __init__(self, parent=None):
super(Editor, self).__init__(parent)
class Main(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.initUi()
def initUi(self):
self.setWindowTitle("Editor")
self.resize(640, 480)
newAc = QtGui.QAction('New', self)
newAc.setShortcut('Ctrl+N')
newAc.triggered.connect(self.new_)
menu = self.menuBar()
filemenu = menu.addMenu('&File')
filemenu.addAction(newAc)
self.tab = QtGui.QTabWidget(self)
self.setCentralWidget(self.tab)
self.tab.addTab(Editor(), "New Text")
def new_(self):
self.tab.addTab(Editor(), "New text")
def main():
import sys
app = QtGui.QApplication(sys.argv)
w = Main()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
I am trying to create an application window with PyQt4. I want to create a window with a frame and inside that frame some widgets such as labels and text editors.
I created the frame as a QGroupBox to be able to put a title on it.
I know that HBox and VBox seem to be the prefered layout when you deal with frames, however, I would like to manage the positionning of the widgets inside my frame with a grid Layout, which I find easier to manage.
So I tried this piece of code :
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QtGui.QHBoxLayout()
grid = QtGui.QGridLayout()
#Definition des Tracing Parameters widgets
WindowSize = QtGui.QLabel("Window size (m)")
SampPts = QtGui.QLabel("Sampling points")
WindowSizeEdit = QtGui.QLineEdit()
SampPtsEdit = QtGui.QLineEdit()
TracParamFrame = QtGui.QGroupBox(self)
TracParamFrame.setTitle("Tracing Parameters")
hbox.addLayout(grid)
grid.addWidget(WindowSize,0,0)
grid.addWidget(WindowSizeEdit,0,1)
grid.addWidget(SampPts,1,0)
grid.addWidget(SampPtsEdit,1,1)
self.setLayout(hbox)
self.setGeometry(300,300,350,300)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The main idea here was to create an hbox where I put the QGroupBox and then place a grid layout inside.
The problem is that in the application generated, the widgets are placed outside the frame, and in addition I get the error :
QLayout: Attempting to add QLayout "" to Example "", which already has a layout
QWidget::setLayout: Attempting to set QLayout "" on Example "", which already has a layout
I modified your code, by adding this statement: TracParamFrame.setLayout(hbox)
The code with this added is as:
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QtGui.QHBoxLayout()
grid = QtGui.QGridLayout()
#Definition des Tracing Parameters widgets
WindowSize = QtGui.QLabel("Window size (m)")
SampPts = QtGui.QLabel("Sampling points")
WindowSizeEdit = QtGui.QLineEdit()
SampPtsEdit = QtGui.QLineEdit()
TracParamFrame = QtGui.QGroupBox(self)
TracParamFrame.setTitle("Tracing Parameters")
hbox.addLayout(grid)
grid.addWidget(WindowSize,0,0)
grid.addWidget(WindowSizeEdit,0,1)
grid.addWidget(SampPts,1,0)
grid.addWidget(SampPtsEdit,1,1)
TracParamFrame.setLayout(hbox)
#self.setLayout(hbox)
self.setGeometry(300,300,350,300)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Ok forget it, I found the solution. I had to use the setLayout method of the GroupBox as follows :
TracParamFrame.setLayout(grid)