How can I put stuff in the main window? I want to create a line edit in the main window(beneath the menu bar, maybe with some decription laber in front of it). How is this done? I used grid layout and this box layout, nothing works.
(sry for another trivial question, there are only few tutorials on pyside out there, and most of them only cover how to create single windows with buttons ect.)
import sys
from PySide import QtGui, QtCore, QtWebKit
class FirstClass(QtGui.QMainWindow, QtGui.QWidget):
def __init__(self):
super(FirstClass, self).__init__()
self.startingUI()
def startingUI(self):
self.setWindowTitle('Hauptfenster')
self.resize(800, 400)
self.statusBar()
#Menueinstellungen an sich
menue = self.menuBar()
#Actions des Menues:
#datei menue
menuleiste_datei = menue.addMenu('File')
datei_exit = QtGui.QAction('Exit', self)
datei_exit.setStatusTip('Close the programm')
menuleiste_datei.addAction(datei_exit)
datei_exit.triggered.connect(self.close)
#Einstellungen menue
menuleiste_configurations = menue.addMenu('Configurations')
configurations_settings = QtGui.QAction('Settings', self)
configurations_settings.setStatusTip('Configurations(Settings)')
menuleiste_configurations.addAction(configurations_settings)
configurations_settings.triggered.connect(self.newwindow)
self.lineedit = QtGui.QLineEdit()
self.layout = QtGui.QHBoxLayout()
self.layout.addWidget(self.lineedit)
self.setLayout(self.layout)
self.show()
def newwindow(self):
self.wid = QtGui.QWidget()
self.wid.resize(250, 150)
self.setWindowTitle('NewWindow')
self.wid.show()
def main():
app = QtGui.QApplication(sys.argv)
start = FirstClass()
sys.exit(app.exec_())
if __name__== '__main__':
main()
I do not believe creating a class with a multiple inheritance is recommended best practice. If an attribute is not found in FirstClass, then it searches left to right (QtGui.QMainWindow to QtGui.QWidget). From my perspective, this would turn into a nightmare to support and debug. My guess this is why the self.layout is not working properly.
I made separate classes for QtGui.QMainWindow and QtGui.QWidget. FirstWindowClass sets the central widget as FirstWidgetClass. FirstWidgetClass has your QLineEdit and I went ahead and inserted a label. I changed QHBoxLayout to QGridLayout to help you understand how it works.
Some tips from my learning experiences with Python and Pyside these past couple months:
Remember you can always look at PyQt examples and majority will work directly with PySide modules.
I recommend looking over http://srinikom.github.io/pyside-docs/index.html as a lot of the modules have simple examples.
For my personal project, a lot of the solutions to my Qt questions were in C++ so do not be afraid to convert it to python.
import sys
from PySide import QtGui, QtCore, QtWebKit
class FirstWindowClass(QtGui.QMainWindow):
def __init__(self):
super(FirstWindowClass, self).__init__()
self.setWindowTitle('Hauptfenster')
self.resize(800, 400)
self.statusBar()
# Set central widget that expands to fill your window
self.main_widget = FirstWidgetClass(self)
self.setCentralWidget(self.main_widget)
#Menueinstellungen an sich
menue = self.menuBar()
#Actions des Menues:
#datei menue
menuleiste_datei = menue.addMenu('File')
datei_exit = QtGui.QAction('Exit', self)
datei_exit.setStatusTip('Close the programm')
menuleiste_datei.addAction(datei_exit)
datei_exit.triggered.connect(self.close)
#Einstellungen menue
menuleiste_configurations = menue.addMenu('Configurations')
configurations_settings = QtGui.QAction('Settings', self)
configurations_settings.setStatusTip('Configurations(Settings)')
menuleiste_configurations.addAction(configurations_settings)
configurations_settings.triggered.connect(self.newwindow)
# Open the window
self.show()
def newwindow(self):
self.wid = QtGui.QWidget()
self.wid.resize(250, 150)
self.wid.setWindowTitle('NewWindow')
self.wid.show()
class FirstWidgetClass(QtGui.QWidget):
def __init__(self, parent=None):
super(FirstWidgetClass, self).__init__()
self.label_example = QtGui.QLabel('Enter Data:')
self.lineedit = QtGui.QLineEdit()
self.layout = QtGui.QGridLayout()
self.layout.addWidget(self.label_example, 0, 0)
self.layout.addWidget(self.lineedit, 0, 1)
self.setLayout(self.layout)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
start = FirstWindowClass()
sys.exit(app.exec_())
if __name__== '__main__':
main()
Related
all.
I'd like to be able to switch between multiple screens. Meaning, the first one is the main, then when with a button or an external switch is activated I can see the page #2, in that one I may have an other button to return to the first one, or going to #3, etc. Cause I have a main screen for a big RPM meter, but I may want to see instead all three meter on the same page, or view the raw data in an other page, or go to the set-up page or elsewhere in the future development. I'm using the full screen space for my graphic. Maybe something like "hide" or "show" a page with an event of some kind. I have a single class script for every pages so far, but unable to group them in a single one. Thanks for your help
I wrote about this concept several years ago here. I went ahead an reproduced the example from that article:
import wx
import wx.grid as gridlib
class PanelOne(wx.Panel):
""""""
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
txt = wx.TextCtrl(self)
class PanelTwo(wx.Panel):
""""""
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
grid = gridlib.Grid(self)
grid.CreateGrid(25,12)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(grid, 0, wx.EXPAND)
self.SetSizer(sizer)
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY,
"Panel Switcher Tutorial")
self.panel_one = PanelOne(self)
self.panel_two = PanelTwo(self)
self.panel_two.Hide()
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.panel_one, 1, wx.EXPAND)
self.sizer.Add(self.panel_two, 1, wx.EXPAND)
self.SetSizer(self.sizer)
menubar = wx.MenuBar()
fileMenu = wx.Menu()
switch_panels_menu_item = fileMenu.Append(wx.ID_ANY,
"Switch Panels",
"Some text")
self.Bind(wx.EVT_MENU, self.onSwitchPanels,
switch_panels_menu_item)
menubar.Append(fileMenu, '&File')
self.SetMenuBar(menubar)
def onSwitchPanels(self, event):
""""""
if self.panel_one.IsShown():
self.SetTitle("Panel Two Showing")
self.panel_one.Hide()
self.panel_two.Show()
else:
self.SetTitle("Panel One Showing")
self.panel_one.Show()
self.panel_two.Hide()
self.Layout()
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
The basic idea here is to Hide() one panel and Show() another. You might also want to look at the Notebook controls that wxPython provides as they have a similar functionality.
I had tried various workarounds about this problem and tried to fix code according to other examples, but ultimately I had failed to make a workable code. While I do have idea of why it fails, I lack skill to create a workaround about this error. Could you please help me with making this code to work?
The problem:
Then I press ''Duomenų apdorojimas'' and proceed to press ''Pavaizduoti signalą'' I get error saying: QCoreApplication::exec: The event loop is already running. I tried various workarounds about this and some legacy code is left inside my functions. I will tidy and optimize my code later, I just need to know how to work properly with GUI in order to avoid this problem. If needed I will send you entire program with txt files, but this part is essential and here problem arises.
import os
import os.path
from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
from tkinter import *
import tkinter.messagebox
import sys
from functools import partial
import matplotlib.pyplot as p
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50, 500, 300)
self.setWindowTitle("")
self.setWindowIcon(QtGui.QIcon('pythonlogo.png'))
openFile = QtGui.QAction("&Atverkite duomenų failą", self)
openFile.setShortcut("Ctrl+Q")
openFile.setStatusTip('Duomenų failas')
openFile.triggered.connect(self.file_open)
extractAction = QtGui.QAction("&Duomenys iš Arduino", self)
extractAction.setShortcut("Ctrl+W")
extractAction.setStatusTip('Prijunkite iš Arduino ateinančius duomenis')
extractAction.triggered.connect(self.upload_usb)
saveFile = QtGui.QAction("&Įšsaugoti failą", self)
saveFile.setShortcut("Ctrl+E")
saveFile.setStatusTip('Nurodykite failo direktoriją bei pavadinimą')
saveFile.triggered.connect(self.file_save)
quitFile = QtGui.QAction("&Išeiti", self)
quitFile.setShortcut("Ctrl+R")
quitFile.setStatusTip('Programa bus uždaryta')
quitFile.triggered.connect(self.close_application)
openEditor = QtGui.QAction("&Skaitytuvas", self)
openEditor.setShortcut("Ctrl+T")
openEditor.setStatusTip('Skaitytuvas visados įjungtas')
openEditor.triggered.connect(self.editor)
additionalData = QtGui.QAction("&Paciento duomenys", self)
additionalData.setShortcut("Ctrl+A")
additionalData.setStatusTip('Įveskite paciento amžiaus grupę')
additionalData.triggered.connect(self.group)
dataProcessing = QtGui.QAction("&Filtruoti signalą", self)
dataProcessing.setShortcut("Ctrl+S")
dataProcessing.setStatusTip('Bus atliekami signalo apdorojimo procesai')
dataProcessing.triggered.connect(self.editor)
showGraph = QtGui.QAction("&Pavaizduoti signalą", self)
showGraph.setShortcut("Ctrl+D")
showGraph.setStatusTip('Bus atvaizduotas šiuo metu turimas signalas')
showGraph.triggered.connect(self.close_application)
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('&Progamos funkcijos')
fileMenu.addAction(openFile)
fileMenu.addAction(extractAction)
fileMenu.addAction(saveFile)
fileMenu.addAction(quitFile)
resultsMenu = mainMenu.addMenu("&Duomenų apdorojimas")
resultsMenu.addAction(dataProcessing)
resultsMenu.addAction(showGraph)
editorMenu = mainMenu.addMenu("&Programos nustatymai")
editorMenu.addAction(openEditor)
editorMenu.addAction(additionalData)
self.statusBar()
self.home()
def openFile(self,n):
print(n)
def home(self):
self.show()
def close_application(self):
graphics()
sys.exit()
def run():
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
run()
Well, it turns out that I was trying to open semi-new program in graphics(). I found out how not to create GUI. Thank you for you help, but I have found out solution. For the next time I will post code in onedrive or something in order for people to get whole program with its supporting documents.
I'm working on a GUI that basically hold multiple widgets that each contain a figure as well as a few buttons/whatever. One of the figures is supposed to be interactive, calling a function whenever the user clicks on any part of the plot. Yet I can't get the function to fire using mpl_connect, even after playing with focus and whatnot. I'm somewhat new to PySide/Qt, so I don't exactly understand why my code is behaving like this (I've been searching for days for a solution, but haven't found anything about it).
I used Qt Designer to create the layout for the GUI. I'm using Spyder from Anaconda 2.2.0 (32-bit), Python 2.7, and PySide to develop the GUI. If it's any help, I come from more of a MATLAB background where I developed a full version of the GUI I'm trying to make in Python.
Below is the relevant code (scroll down a bit to see where the problem is):
from PySide import QtCore, QtGui
from PySide.QtCore import *
from PySide.QtGui import *
import numpy as np
import matplotlib
matplotlib.use('Qt4Agg')
matplotlib.rcParams['backend.qt4']='PySide'
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
import matplotlib.pyplot as plt
from PySide.QtGui import QPalette, QCursor
import matplotlib.colors as colors
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1316, 765)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.widget = QtGui.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(75, 40, 375, 490))
self.widget.setObjectName("widget")
color = self.centralwidget.palette().color(QPalette.Window)
self.leftPlot = MatplotlibWidget(None,'','','',False,color)
self.setupPlot(self.widget,self.leftPlot)
self.leftPlot.figure.tight_layout()
self.leftImage = self.leftPlot.axes.imshow(self.defaultSlide, cmap = mymap)
Snippet of interest:
self.leftPlot.figure.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
self.leftPlot.figure.canvas.setFocus()
cid = self.leftPlot.figure.canvas.mpl_connect('button_release_event', self.getCoordinates) # doesn't get called
plt.show()
def getCoordinates(self, event):
print 'dasdsadadsa'
print 'button=%d, x=%d, y=%d, xdata=%f, ydata=%f'%(event.button, event.x, event.y, event.xdata, event.ydata)
The rest:
class MatplotlibWidget(FigureCanvas):
def __init__(self, parent=None,xlabel='x',ylabel='y',title='Title',showTicks=False,color=None):
super(MatplotlibWidget, self).__init__(Figure())
self.setParent(parent)
if color != None:
self.figure = Figure(facecolor=(color.red()/256.0,color.green()/256.0,color.blue()/256.0),frameon=0)
else:
self.figure = Figure(frameon=0)
self.canvas = FigureCanvas(self.figure)
self.axes = self.figure.add_subplot(111)
self.axes.set_xlabel(xlabel)
self.axes.set_ylabel(ylabel)
self.axes.set_title(title)
self.axes.get_xaxis().set_visible(showTicks)
self.axes.get_yaxis().set_visible(showTicks)
class ControlMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(ControlMainWindow, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
plt.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
mySW = ControlMainWindow()
mySW.show()
sys.exit(app.exec_())
I'm aware the code is messy, but any input is greatly appreciated.
Update (2015-09-04) : I've updated the MWE I provided as part of my original answer to use instead the approach that is suggested in the matplotlib documentation to embed a mpl figure in an application. This approach does not use the pyplot interface (as in my original answer) and use the Object Oriented API of mpl instead. Also, since all the mpl artists (figure, axes, etc.) know each other, there is no need to explicitly create new class variables. This allows a structure of code that is, IMO, easier to read and to maintain.
The problem comes from the fact that you are not connecting correctly your event to self.leftPlot (FigureCanvasQTAgg), but to self.leftPlot.figure.canvas (FigureCanvasQTAgg.figure.FigureCanvasQTAgg) instead. You are creating a canvas within a canvas in the MatplotlibWidget class (which is already a subclass of FigureCanvasQTAgg). You only need to create one mpl canvas, pass a figure to it, and then connect the event to it directly.
I've put together a MWE to demonstrate how this can be done using the Object Oriented API of Matplotlib as suggested in the documentation:
from PySide import QtGui
import numpy as np
import sys
import matplotlib as mpl
mpl.use('Qt4Agg')
mpl.rcParams['backend.qt4']='PySide'
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg
class ControlMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(ControlMainWindow, self).__init__(parent)
self.setupUi()
def setupUi(self):
figure = mpl.figure.Figure(figsize=(5, 5))
leftPlot = MatplotlibWidget(figure)
self.setCentralWidget(leftPlot)
class MatplotlibWidget(FigureCanvasQTAgg):
def __init__(self, fig):
super(MatplotlibWidget, self).__init__(fig)
#-- set up an axe artist --
ax = fig.add_axes([0.1, 0.1, 0.85, 0.85])
ax.plot(np.arange(15), np.arange(15))
self.draw()
#---- setup event ----
self.mpl_connect('button_press_event', self.onclick)
def onclick(self, event):
x, y = event.x, event.y
print(x, y)
if x != None and y != None:
ax = self.figure.axes[0]
ax.plot(event.xdata, event.ydata, 'ro')
self.draw()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
mySW = ControlMainWindow()
mySW.show()
sys.exit(app.exec_())
The code above results in:
I want to run my app in different tabs. Rightnow, it is running in main window. I have done some search work on how to create tabs. I found this to be useful, but not sufficient to meet my requirements
Create TAB and create textboxes that take data in the TAB-page
I want to have a feature of adding a new tab (like new tab in chrome)
Below is my code sample. I described what i require in the comments.
from PyQt4 import Qt, QtCore, QtGui
import sys
class Map(QtGui.QMainWindow):
def __init__(self,parentQExampleScrollArea=None,parentQWidget = None):
super(Map,self).__init__()
self.initUI()
#Initialize the UI
def initUI(self):
#Initilizing Menus toolbars
#This must be maintained in all tabbed panes
filename = ""
#Filename is obtained through open file button in file menu
self.filename = filename
def paintEvent(self, e):
qp = QtGui.QPainter()
qp.begin(self)
self.drawPoints(qp,self.filename)
qp.end()
def drawPoints(self, qp,FILENAME=""):
#Read contents in file
#Get the necessary coordinates
#A separate class for storing the info of all the coordinates
#Run a for loop for all the coordinates in the list
#Actually, object is created here and image of that object is set
# as a square using the coordinates
qp.setBrush(QtGui.QColor(255, 0, 20, 200))
qp.drawRect(20,20,75,75)
qp.drawRect(100,20,75,75)
self.update()
#There are many functions to handle keyboard and mouse events
def main():
#How do I modify so that I can have multiple tabs
#And show images of the coordinates in files
#Basically I want to have the feature of opening many files
# and displaying them in UI
#Basically a feature to add a new tab
#like that of in eclipse netbeans sublime etc
app = QtGui.QApplication(sys.argv)
myQExampleScrollArea = Map()
myQExampleScrollArea.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Thanks in advance.. :)
It's simply to use method int QTabWidget.addTab (self, QWidget widget, QString) to create widget in tab. In each tab, I suggest use QtGui.QWidget more than QtGui.QMainWindow;
Example;
import sys
from PyQt4 import QtGui
class QCustomWidget (QtGui.QWidget):
# Your widget to implement
# Put your override method here
def paintEvent (self, eventQPaintEvent):
currentQPainter = QtGui.QPainter()
currentQPainter.begin(self)
currentQPainter.setBrush(QtGui.QColor(255, 0, 20, 200))
currentQPainter.drawRect(20, 20, 75, 75)
currentQPainter.drawRect(100, 20, 75, 75)
self.update()
currentQPainter.end()
class QCustomTabWidget (QtGui.QTabWidget):
def __init__ (self, parent = None):
super(QCustomTabWidget, self).__init__(parent)
self.addTab(QtGui.QPushButton('Test'), 'Tab 1')
self.addTab(QCustomWidget(), 'Tab 2')
myQApplication = QtGui.QApplication([])
myQCustomTabWidget = QCustomTabWidget()
myQCustomTabWidget.show()
sys.exit(myQApplication.exec_())
So handle with more tab, It's bad to create many line call int QTabWidget.addTab (self, QWidget widget, QString). Anyway, All widget has add in QTabWidget is can reference in ifself. So, your can control element in it by call QWidget QTabWidget.widget (self, int index).
Example to call widget in tab widget;
import os
import sys
from PyQt4 import QtCore, QtGui
class QCustomLabel (QtGui.QLabel):
def __init__(self, imagePath, parentQWidget = None):
super(QCustomLabel, self).__init__(parentQWidget)
self.setPixmap(QtGui.QPixmap(imagePath))
class QCustomWidget (QtGui.QWidget):
def __init__ (self, parentQWidget = None):
super(QCustomWidget, self).__init__(parentQWidget)
self.addQPustButton = QtGui.QPushButton('Open image')
self.addQPustButton.setMaximumWidth(120)
self.addQPustButton.released.connect(self.openImage)
self.workSpaceQTabWidget = QtGui.QTabWidget()
self.workSpaceQTabWidget.setTabsClosable(True)
self.workSpaceQTabWidget.tabCloseRequested.connect(self.closeImage)
allQVBoxLayout = QtGui.QVBoxLayout()
allQVBoxLayout.addWidget(self.addQPustButton)
allQVBoxLayout.addWidget(self.workSpaceQTabWidget)
self.setLayout(allQVBoxLayout)
def openImage (self):
path = QtGui.QFileDialog.getOpenFileName(self, 'Open image')
if not path.isEmpty():
self.workSpaceQTabWidget.addTab(QCustomLabel(path), QtCore.QString(os.path.basename(str(path))))
def closeImage (self, currentIndex):
currentQWidget = self.workSpaceQTabWidget.widget(currentIndex)
currentQWidget.deleteLater()
self.workSpaceQTabWidget.removeTab(currentIndex)
myQApplication = QtGui.QApplication([])
myQCustomWidget = QCustomWidget()
myQCustomWidget.show()
sys.exit(myQApplication.exec_())
I'm writing a PyQt application that shall feature multiple windows. Right now, I am interested in having one of two windows open at a time (so a click of a button in one window causes a switch to the other window). What is a reasonable way of keeping track of multiple windows in a PyQt application? My initial attempt, as shown below, essentially stores instances of the QtGui.QWidget in data members of a global instance of a simple class.
I'm new to PyQt. Is there a better way to approach this?
#!/usr/bin/env python
import sys
from PyQt4 import QtGui
class Program(object):
def __init__(
self,
parent = None
):
self.interface = Interface1()
class Interface1(QtGui.QWidget):
def __init__(
self,
parent = None
):
super(Interface1, self).__init__(parent)
self.button1 = QtGui.QPushButton(self)
self.button1.setText("button")
self.button1.clicked.connect(self.clickedButton1)
self.layout = QtGui.QHBoxLayout(self)
self.layout.addWidget(self.button1)
self.setGeometry(0, 0, 350, 100)
self.setWindowTitle('interface 1')
self.show()
def clickedButton1(self):
self.close()
program.interface = Interface2()
class Interface2(QtGui.QWidget):
def __init__(
self,
parent = None
):
super(Interface2, self).__init__(parent)
self.button1 = QtGui.QPushButton(self)
self.button1.setText("button")
self.button1.clicked.connect(self.clickedButton1)
self.layout = QtGui.QHBoxLayout(self)
self.layout.addWidget(self.button1)
self.setGeometry(0, 0, 350, 100)
self.setWindowTitle('interface 2')
self.show()
def clickedButton1(self):
self.close()
program.interface = Interface1()
def main():
application = QtGui.QApplication(sys.argv)
application.setApplicationName('application')
global program
program = Program()
sys.exit(application.exec_())
if __name__ == "__main__":
main()
Have a single main window with a QStackedWidget to hold the different interfaces. Then use QStackedWidget.setCurrentIndex to switch between the interfaces.
Also, try to avoid using global references. If you want GUI components to communicate with each other, use signals and slots. You can easily define your own custom signals if there are no suitable built-in ones.