Trying to plot a pie chart with python in PyQt5 and Matplotlib and I'm having some issues. I'm able to have a pie chart and the data I want to display in it, but I'm trying to update the chart if I feed it new data when I call a certain function.
mplvl is the widget name that I am adding the figure to.
Every time I call this function it just adds another subplot. I've tried clearing the plot, clearing the figure, but I cannot get it to just delete and redraw the figure. I think I'm confused at how Matplotlib truly works, but any help would be appreciated.
import datetime
import calendar as cal
import sys
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow, QMessageBox, QTableWidgetItem
from PyQt5.uic import loadUi
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import (FigureCanvasQTAgg as FigureCanvas)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
loadUi('main.ui', self)
self.date_from.setDate(QtCore.QDate(c_date.year, c_date.month, 1))
self.date_to.setDate(QtCore.QDate(c_date.year, c_date.month, cal.monthrange(c_date.year, c_date.month)[1]))
self.date_from.dateChanged.connect(self.fcn_date_changed)
self.date_to.dateChanged.connect(self.fcn_date_changed)
def fcn_date_changed(self):
print("from: " + self.date_from.text() + " to: " + self.date_to.text())
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]
fig = Figure()
ax1 = fig.add_subplot(111)
ax1.set_title('Percentage Spending by Category')
ax1.pie(sizes, labels=labels, autopct='%1.1f%%', shadow=False, startangle=90)
main.canvas = FigureCanvas(fig)
main.mplvl.addWidget(main.canvas)
if __name__ == "__main__":
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
Below is main.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>861</width>
<height>611</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="btn_add_item">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>71</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>Add Item</string>
</property>
</widget>
<widget class="QPushButton" name="btn_edit_item">
<property name="geometry">
<rect>
<x>190</x>
<y>540</y>
<width>81</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Edit Item</string>
</property>
</widget>
<widget class="QListWidget" name="recent_items">
<property name="geometry">
<rect>
<x>10</x>
<y>130</y>
<width>351</width>
<height>401</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="lbl_recent_items">
<property name="geometry">
<rect>
<x>10</x>
<y>110</y>
<width>251</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Recent Items</string>
</property>
</widget>
<widget class="QPushButton" name="btn_delete_item">
<property name="geometry">
<rect>
<x>280</x>
<y>540</y>
<width>81</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Delete Item</string>
</property>
</widget>
<widget class="QWidget" name="mplwindow" native="true">
<property name="geometry">
<rect>
<x>380</x>
<y>130</y>
<width>471</width>
<height>401</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="mplvl"/>
</widget>
<widget class="QPushButton" name="btn_view_items">
<property name="geometry">
<rect>
<x>280</x>
<y>100</y>
<width>81</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>View Items</string>
</property>
</widget>
<widget class="QDateEdit" name="date_from">
<property name="geometry">
<rect>
<x>110</x>
<y>60</y>
<width>110</width>
<height>21</height>
</rect>
</property>
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
<widget class="QDateEdit" name="date_to">
<property name="geometry">
<rect>
<x>250</x>
<y>60</y>
<width>110</width>
<height>21</height>
</rect>
</property>
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="lbl_showing_items1">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>101</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Showing items from: </string>
</property>
</widget>
<widget class="QLabel" name="lbl_showing_items1_2">
<property name="geometry">
<rect>
<x>230</x>
<y>60</y>
<width>21</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>to:</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>861</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
The logic is to:
create a single AxesSubplot,
clean it,
call the function that implements the plot (in your case pie()) and
call draw() to paint it.
# ...
self.date_to.dateChanged.connect(self.fcn_date_changed)
fig = Figure()
self.canvas = FigureCanvas(fig)
self.mplvl.addWidget(self.canvas)
self.ax1 = fig.add_subplot(111)
self.ax1.pie([])
def fcn_date_changed(self):
self.ax1.clear()
self.ax1.set_title("Percentage Spending by Category")
print("from: " + self.date_from.text() + " to: " + self.date_to.text())
labels = "Frogs", "Hogs", "Dogs", "Logs"
sizes = [15, 30, 45, 10]
self.ax1.pie(
sizes, labels=labels, autopct="%1.1f%%", shadow=False, startangle=90
)
self.ax1.figure.canvas.draw()
Related
How to copy tab1 frame to new tab which is dynamically added using QPushButton and addTab function.
Trying to create gui with "Insert Tab" button that will add new tab with predefined frame and settings,
but its replacing frame from tab1 to new tab if I go back to tab one its missing the frame which i used in new tab.
How can I copy the widgets instead of moving it while adding new tab?
ui file:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1120</width>
<height>850</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QTabWidget" name="tabWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>130</y>
<width>1121</width>
<height>721</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(253, 255, 242);</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Tab 1</string>
</attribute>
<widget class="QWidget" name="widget" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1111</width>
<height>691</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(255, 243, 242);</string>
</property>
<widget class="QFrame" name="frame_frame">
<property name="geometry">
<rect>
<x>700</x>
<y>210</y>
<width>171</width>
<height>80</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>30</x>
<y>30</y>
<width>47</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>Hello saqib</string>
</property>
</widget>
</widget>
</widget>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Tab 2</string>
</attribute>
</widget>
</widget>
<widget class="QPushButton" name="change">
<property name="geometry">
<rect>
<x>60</x>
<y>50</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>Change Text</string>
</property>
</widget>
<widget class="QPushButton" name="insert">
<property name="geometry">
<rect>
<x>220</x>
<y>50</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>Insert Tab</string>
</property>
</widget>
<widget class="QPushButton" name="remove">
<property name="geometry">
<rect>
<x>390</x>
<y>50</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>Remove Tab</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
python main:
import sys
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QDialog
from PyQt5.uic import loadUi
from PySide2.QtCore import *
class MainWindow(QDialog):
def __init__(self):
super(MainWindow, self).__init__()
loadUi("tabtutorial.ui", self)
self.tabWidget.currentChanged.connect(self.tabChanged)
self.change.clicked.connect(self.changeTabText)
self.insert.clicked.connect(self.insertTab)
self.remove.clicked.connect(self.removeTab)
def tabChanged(self):
print("Tab was changed to ", self.tabWidget.currentIndex())
def changeTabText(self):
self.tabWidget.setTabText(0, "First tab")
self.tabWidget.setTabText(1, "Second tab")
def insertTab(self):
self.label.setText(QCoreApplication.translate("Dialog", "Hello test", None))
self.tabWidget.addTab(self.widget, "New Tab")
def removeTab(self):
self.tabWidget.removeTab(0)
# main
app = QApplication(sys.argv)
mainwindow = MainWindow()
widget = QtWidgets.QStackedWidget()
widget.addWidget(mainwindow)
widget.setFixedHeight(850)
widget.setFixedWidth(1120)
widget.show()
try:
sys.exit(app.exec_())
except:
print("Exiting")
Output:
this Tab1 have a frame with "Hello Saq" label under frame widget.
If I insert new tab (using the above code addTab(self.widget, "New Tab") function its adding the frame to new tab but now its missing in the Tab1
Is there any way to copy widget instead of moving it?
I have made a Tab Widget Window in my Main Window using Qt-Designer and I am trying to access a button in my 1st Tab.
This is my code.
import sys
from PyQt5 import QtCore, QtGui,uic,QtWidgets
class AddWindow(QtWidgets.QDialog):
def __init__(self):
super(AddWindow,self).__init__()
uic.loadUi('AddWindow.ui',self)
class MyApp(QtWidgets.QMainWindow):
def __init__(self):
super(MyApp,self).__init__()
uic.loadUi('MainWindow.ui',self)
self.AddButton.clicked.connect(self.Addwindow)
def printW(self):
print("hello")
def Addwindow(self):
addwindow=AddWindow()
addwindow.exec_()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
I just want to have my button on 1st tab (named print) connected with function printW So I can display something on screen.
here is my MainWindow.ui file.
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>756</width>
<height>549</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="AddButton">
<property name="geometry">
<rect>
<x>630</x>
<y>440</y>
<width>121</width>
<height>61</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>18</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
<widget class="QPushButton" name="Next">
<property name="geometry">
<rect>
<x>170</x>
<y>420</y>
<width>121</width>
<height>51</height>
</rect>
</property>
<property name="text">
<string>Next</string>
</property>
</widget>
<widget class="QTabWidget" name="tabWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>50</y>
<width>711</width>
<height>311</height>
</rect>
</property>
<property name="currentIndex">
<number>2</number>
</property>
<widget class="QWidget" name="tab1">
<attribute name="title">
<string>Tab 1</string>
</attribute>
<widget class="QPushButton" name="print">
<property name="geometry">
<rect>
<x>190</x>
<y>100</y>
<width>101</width>
<height>51</height>
</rect>
</property>
<property name="text">
<string>print</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="tab2">
<attribute name="title">
<string>tab 2</string>
</attribute>
</widget>
<widget class="QWidget" name="tab3">
<attribute name="title">
<string>Page</string>
</attribute>
</widget>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>756</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
I have tried creating a class and accessing button but could not do it.
I've created a simple GUI using qt designer and imported it into my python project. The main window comes up, and the menus/buttons are responsive, but I cannot manage to connect my QActions to custom functions (I did it for buttons though, and it works). The weird thing is that my custom function (on_action_clicked) is called once when I run the application, but not when I click on the menu items or icons of the toolbar (I tried connecting both). Below are the test codes. Am I missing something?
imbrowser3d.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>851</width>
<height>649</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QGraphicsView" name="gv_image">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>731</width>
<height>501</height>
</rect>
</property>
</widget>
<widget class="QScrollBar" name="sb_index">
<property name="geometry">
<rect>
<x>0</x>
<y>510</y>
<width>701</width>
<height>20</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
<widget class="QScrollBar" name="sb_zeta">
<property name="geometry">
<rect>
<x>0</x>
<y>530</y>
<width>701</width>
<height>20</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
<widget class="QLabel" name="label_index">
<property name="geometry">
<rect>
<x>700</x>
<y>510</y>
<width>55</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>index</string>
</property>
</widget>
<widget class="QLabel" name="label_zeta">
<property name="geometry">
<rect>
<x>700</x>
<y>530</y>
<width>55</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>zeta</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>740</x>
<y>500</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>851</width>
<height>26</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="menu_open"/>
<addaction name="menu_save"/>
<addaction name="menu_load"/>
</widget>
<addaction name="menuFile"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="action_toolbar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="action_save_state"/>
</widget>
<action name="menu_open">
<property name="text">
<string>Open</string>
</property>
</action>
<action name="menu_save">
<property name="icon">
<iconset>
<normaloff>ui_icons/save_icon.png</normaloff>ui_icons/save_icon.png</iconset>
</property>
<property name="text">
<string>Save state</string>
</property>
</action>
<action name="menu_load">
<property name="text">
<string>Load state</string>
</property>
</action>
<action name="action_save_state">
<property name="icon">
<iconset>
<normaloff>ui_icons/save_icon.png</normaloff>ui_icons/save_icon.png</iconset>
</property>
<property name="text">
<string>Save state</string>
</property>
<property name="toolTip">
<string>Save state</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>
main.py
import sys
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication, QAction, QPushButton, QFileDialog
from PySide2.QtCore import QFile, QObject
class UiMainWindow(QObject):
def __init__(self, ui_file, parent=None):
super(UiMainWindow, self).__init__(parent)
ui_file = QFile(ui_file)
ui_file.open(QFile.ReadOnly)
loader = QUiLoader()
self.window = loader.load(ui_file)
ui_file.close()
self.btn = self.window.findChild(QPushButton, 'pushButton')
self.btn.clicked.connect(self.on_btn_clicked)
self.action_save = self.window.findChild(QAction, 'action_save_state')
self.action_save.triggered.connect(self.on_action_clicked('action clicked'))
self.window.show()
def on_action_clicked(self, txt):
print(txt)
def on_btn_clicked():
print('button clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
form = UiMainWindow('imbrowser3d.ui')
sys.exit(app.exec_())
You have 2 errors:
on_btn_clicked is a method of the class so it must have as the first parameter the instance, that is, self.
the connection is with the name of the function without evaluating, in your case the slot on_action_clicked you are evaluating it, so you are getting it printed at the beginning, for it there are 2 possible solutions: use partial or use a lambda function.
self.btn = self.window.findChild(QPushButton, 'pushButton')
self.btn.clicked.connect(self.on_btn_clicked)
self.action_save = self.window.findChild(QAction, 'action_save_state')
self.action_save.triggered.connect(partial(self.on_action_clicked, 'action clicked'))
# self.action_save.triggered.connect(lambda: self.on_action_clicked('action clicked')) # use lambda function
self.window.show()
def on_action_clicked(self, txt):
print(txt)
def on_btn_clicked(self):
print('button clicked')
I decided to implement a simple version of GA algorithm. I firstly use Qt designer to create a .ui document which contains the component and layout of my GUI. Then try to connect it with the python, however, when comes to the self.dis_speed.insert(a), the window closes immediately. This is the whole code:
import sys
import random
import threading
import copy
from PyQt5 import QtCore, QtGui, uic, QtWidgets
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton,QTextEdit,QAction, QLabel,QSpinBox,QLineEdit
from PyQt5.QtCore import pyqtSlot
qtCreatorFile = 'assignment1_gui.ui' # Enter file here.
class Ui(QtWidgets.QMainWindow):
size=0
fit_dict={}
individual=[]
def __init__(self,parent=None):
super(Ui,self).__init__(parent=parent)
s=uic.loadUi(qtCreatorFile, self)
self.show()
self.but_start.clicked.connect(self.start)
self.dis_speed=s.dis_speed
self.dis_fit=s.dis_fit
self.dis_speed.setReadOnly(True)
self.dis_fit.setReadOnly(True)
def init_ind(a):
indi = [[] for l in range(a)]
for i in range(0,a):
for j in range(0,28):
indi[i].append(chr(random.randint(32, 127)))
return indi
def evaluate_fit(target,a):
count=0
for i in range(0,len(target)):
if target[i]==a[i]:
count+=1
return count
return(28-Levenshtein.hamming(str(target),str(a)))
def mutate(a):
for i in range(0,len(a)):
if(random.random()<(1/len(a))):
a[i]=chr(random.randint(32, 127))
return a
def crossover(a,b):
c=list()
for i in range(0,len(a)):
if random.random()<0.5:
c.append(a[i])
else:
c.append(b[i])
return c
def ga_cross(self,individual,target):
ind=copy.deepcopy(Ui.individual)
speed=0
printf=0
while(1):
a=random.randint(0,Ui.size-1)
b=random.randint(0,Ui.size-1)
if Ui.fit_dict[a]>Ui.fit_dict[b]:
parent1=ind[a]
else:
parent1=ind[b]
a=random.randint(0,Ui.size-1)
b=random.randint(0,Ui.size-1)
if Ui.fit_dict[a]>Ui.fit_dict[b]:
parent2=ind[a]
else:
parent2=ind[b]
child=Ui.mutate(Ui.crossover(parent1,parent2))
a=random.randint(0,Ui.size-1)
b=random.randint(0,Ui.size-1)
if Ui.fit_dict[a]>Ui.fit_dict[b]:
ind[b]=child
Ui.fit_dict[b]=Ui.evaluate_fit(target,child)
else:
ind[a]=child
Ui.fit_dict[a]=Ui.evaluate_fit(target,child)
speed+=1
if child==target:
break
if printf%10==0:
res=max(Ui.fit_dict.items(), key=lambda x: x[1])
Ui.tex(str(speed),str(ind[res[0]]))
printf+=1
#pyqtSlot()
def tex(self,a,b):
self.dis_speed.end(False)
self.dis_speed.insert(a) #close immediately
self.dis_fit.end(False)
self.dis_fit.insert(b)
#pyqtSlot()
def start(self):
target=list('methinks it is like a weasel')
Ui.size=int(self.spin_size.value())
Ui.individual=Ui.init_ind(Ui.size)
s=range(0,Ui.size)
ss=[0 for i in range(0,Ui.size)]
Ui.fit_dict=dict(zip(s,ss))
for i in range(0,Ui.size):
Ui.fit_dict[i]=Ui.evaluate_fit(target,Ui.individual[i])
Ui.ga_cross(self,Ui.individual,target)
Ui.ga_nocross(self,Ui.individual,target)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = Ui()
window.show()
sys.exit(app.exec_())
The following page is the .ui document in XML format which can be directly copied.
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>957</width>
<height>717</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QLabel" name="lab_title">
<property name="geometry">
<rect>
<x>100</x>
<y>40</y>
<width>811</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>36</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Comparision between GA with&without crossover</string>
</property>
</widget>
<widget class="QSpinBox" name="spin_size">
<property name="geometry">
<rect>
<x>590</x>
<y>120</y>
<width>111</width>
<height>41</height>
</rect>
</property>
<property name="minimum">
<number>100</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="displayIntegerBase">
<number>10</number>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>310</x>
<y>130</y>
<width>271</width>
<height>20</height>
</rect>
</property>
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>18</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Please select the size of population:</string>
</property>
</widget>
<widget class="QPushButton" name="but_start">
<property name="geometry">
<rect>
<x>380</x>
<y>190</y>
<width>191</width>
<height>71</height>
</rect>
</property>
<property name="font">
<font>
<family>Wingdings 2</family>
<pointsize>24</pointsize>
</font>
</property>
<property name="text">
<string>START!</string>
</property>
</widget>
<widget class="QLabel" name="lab_nocr">
<property name="geometry">
<rect>
<x>30</x>
<y>330</y>
<width>241</width>
<height>51</height>
</rect>
</property>
<property name="font">
<font>
<family>Trajan Pro</family>
<pointsize>18</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Speed of no crossover:</string>
</property>
</widget>
<widget class="QLabel" name="lab_cr">
<property name="geometry">
<rect>
<x>590</x>
<y>330</y>
<width>211</width>
<height>51</height>
</rect>
</property>
<property name="font">
<font>
<family>Trajan Pro</family>
<pointsize>18</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Speed of crossover:</string>
</property>
</widget>
<widget class="QLabel" name="lab_nfit">
<property name="geometry">
<rect>
<x>130</x>
<y>410</y>
<width>111</width>
<height>16</height>
</rect>
</property>
<property name="font">
<font>
<family>YuMincho</family>
<pointsize>18</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Fittest Now:</string>
</property>
</widget>
<widget class="QLabel" name="lab_fit">
<property name="geometry">
<rect>
<x>690</x>
<y>410</y>
<width>111</width>
<height>16</height>
</rect>
</property>
<property name="font">
<font>
<family>YuMincho</family>
<pointsize>18</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Fittest Now:</string>
</property>
</widget>
<widget class="QLineEdit" name="dis_nspeed">
<property name="geometry">
<rect>
<x>270</x>
<y>340</y>
<width>51</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="dis_nfit">
<property name="geometry">
<rect>
<x>20</x>
<y>440</y>
<width>341</width>
<height>41</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="dis_speed">
<property name="geometry">
<rect>
<x>800</x>
<y>340</y>
<width>41</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="dis_fit">
<property name="geometry">
<rect>
<x>600</x>
<y>440</y>
<width>291</width>
<height>41</height>
</rect>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>957</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
I am starting using QtCreator to create a UI for a little tool for Maya 2017. QtCreator gave me this .ui file :
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DockWidget</class>
<widget class="QDockWidget" name="DockWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>550</width>
<height>251</height>
</rect>
</property>
<property name="floating">
<bool>true</bool>
</property>
<property name="windowTitle">
<string>Attr Editor</string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<widget class="QLineEdit" name="attr_value_textfield">
<property name="geometry">
<rect>
<x>130</x>
<y>128</y>
<width>391</width>
<height>20</height>
</rect>
</property>
<property name="toolTip">
<string>attr_value</string>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>227</x>
<y>20</y>
<width>97</width>
<height>25</height>
</rect>
</property>
<property name="font">
<font>
<family>Century Gothic</family>
<pointsize>16</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Attr Editor</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_2">
<property name="geometry">
<rect>
<x>240</x>
<y>180</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Submit</string>
</property>
<property name="+command" stdset="0">
<string>submitCommand</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>20</x>
<y>130</y>
<width>80</width>
<height>16</height>
</rect>
</property>
<property name="font">
<font>
<family>Century Gothic</family>
</font>
</property>
<property name="text">
<string>Attribute Value</string>
</property>
</widget>
<widget class="QLineEdit" name="attr_name_textfield">
<property name="geometry">
<rect>
<x>130</x>
<y>78</y>
<width>391</width>
<height>20</height>
</rect>
</property>
<property name="toolTip">
<string>attr_name</string>
</property>
<property name="whatsThis">
<string/>
</property>
</widget>
<widget class="QPushButton" name="pushButton_3">
<property name="geometry">
<rect>
<x>440</x>
<y>180</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Cancel</string>
</property>
<property name="+command" stdset="0">
<string>cancelCommand</string>
</property>
</widget>
<widget class="QPushButton" name="display_button">
<property name="geometry">
<rect>
<x>30</x>
<y>180</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Display</string>
</property>
<property name="+command" stdset="0">
<string>displayCommand</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>20</x>
<y>80</y>
<width>82</width>
<height>16</height>
</rect>
</property>
<property name="font">
<font>
<family>Century Gothic</family>
</font>
</property>
<property name="text">
<string>Attribute Name</string>
</property>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>
And I have this code wich displays my UI :
import maya.cmds as cmds
from PySide2.QtWidgets import *
from PySide2.QtCore import *
if cmds.window(main_window, ex = True):
cmds.deleteUI(main_window)
main_window = cmds.loadUI(uiFile = "C:/Users/thornydre/Desktop/attreditorui.ui")
cmds.showWindow(main_window)
def displayCommand(e):
print(attr_name_textfield.text())
print(attr_value_textfield.text())
def submitCommand(e):
attr_name = attr_name_textfield.text()
attr_value = attr_value_textfield.text()
is_string = False
try:
new_attr_value = float(attr_value)
if float(attr_value) % 1 == 0:
new_attr_value = int(attr_value)
except:
is_string = True
new_attr_value = attr_value
print(new_attr_value)
for name in cmds.ls(sl = True):
if is_string:
cmds.setAttr(name + "." + attr_name, new_attr_value, type = "string")
else:
cmds.setAttr(name + "." + attr_name, new_attr_value)
def cancelCommand(e):
cmds.deleteUI(main_window, window = True)
And if I click on my display_button, I have an error :
# Result: dockWidgetContents|display_button #
# Error: AttributeError: file <maya console> line 12: 'bool' object has no attribute 'attr_name_textfield' #
I tried to do it with a subclass of QtWidgets.QWidget as I found somewhere on the internet, but I don't really found any tutorial on how to build it properly:
from PySide2 import QtCore, QtGui, QtWidgets, QtUiTools
class Interface(QtWidgets.QWidget):
def __init__(self, parent = None):
super(Interface, self).__init__(parent)
ui_filename = "C:/Users/thornydre/Desktop/attreditorui.ui"
ui_file = QtCore.QFile(ui_filename)
ui_file.open(QtCore.QFile.ReadOnly)
self.ui = QtUiTools.QUiLoader().load(ui_file, parentWidget=self)
ui_file.close()
def connectInterface(self):
QtCore.QtObject.connect(self.displayCommand, QtCore.SIGNAL("clicked()"), self.displayCommandWin)
def displayCommand(self):
print(self.attr_name_textfield.text())
print(self.attr_value_textfield.text())
def main():
global ui
ui = Interface()
if __name__ == "__main__":
main()
Same thing here, the UI shows up, but really nothing happens with clicking on the display_button
Your second try with the class seems good but it's completely normal that you can't execute displayCommand, your button is not connected to your method.
Juste delete your connectInterface method, and right after ui_file.close() copy this:
self.ui.display_button.clicked.connect(self.displayCommand)
It should work better :) (and you have to use the eyllanesc solution too to access to the widgets values)