PyQt5 - not able to add elements to QTabWidget - python

I am trying to add a second tab (containing a pie chart visualization) to my PyQt5 GUI, but I cannot figure out how to display it. This second tab is laid out in a separate class and my program has the following structure:
main.py
from PyQt5 import QtWidgets, QtCore
from gui import UiMainWindow
import sys
class Logic(QtWidgets.QMainWindow, UiMainWindow,):
def __init__(self):
super().__init__()
self.setupUi(self)
self.treeView = QtWidgets.QTreeView(self.tabwidget.main_tab)
self.treeView.setGeometry(QtCore.QRect(270, 90, 801, 571))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
logic = Logic()
logic.show()
sys.exit(app.exec_())
gui.py
from PyQt5 import QtWidgets, QtCore
from main_tab import MainTab
class UiMainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("Invoice Manager")
MainWindow.resize(1120, 750)
MainWindow.setTabShape(QtWidgets.QTabWidget.Rounded)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.tabwidget = MainTab(self.centralwidget)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
self.tabwidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("Test", "Test"))
self.tabwidget.setTabText(
self.tabwidget.indexOf(self.tabwidget.main_tab),
_translate("MainWindow", "Main"))
self.tabwidget.setTabText(
self.tabwidget.indexOf(self.tabwidget.visual_tab),
_translate("MainWindow", "Tab_2"))
main_tab.py
from PyQt5 import QtCore, QtWidgets
from tab_2 import Tab2
class MainTab(QtWidgets.QTabWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setGeometry(QtCore.QRect(0, 0, 1120, 750))
self.main_tab = QtWidgets.QWidget()
self.addTab(self.main_tab, "")
self.visual_tab = Tab2()
self.addTab(self.visual_tab, "")
tab_2.py
from PyQt5 import QtWidgets
from PyQt5.QtChart import QChart, QChartView, QPieSeries, QPieSlice
from PyQt5.QtGui import QPainter, QPen
from PyQt5.QtCore import Qt
class Tab2(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.layout = QtWidgets.QVBoxLayout()
self.setLayout(self.layout)
self.create_piechart()
def create_piechart(self):
series = QPieSeries()
series.append("Label 1", 2)
series.append("Label 2", 2)
series.append("Label 3", 2)
pie_slice = QPieSlice()
pie_slice.setExploded(True)
pie_slice.setLabelVisible(True)
pie_slice.setPen(QPen(Qt.darkGreen, 2))
pie_slice.setBrush(Qt.green)
chart = QChart()
chart.legend().hide()
chart.addSeries(series)
chart.createDefaultAxes()
chart.setAnimationOptions(QChart.SeriesAnimations)
chart.setTitle("Pie Chart Example")
chart.legend().setVisible(True)
chart.legend().setAlignment(Qt.AlignBottom)
chartview = QChartView(chart)
chartview.setRenderHint(QPainter.Antialiasing)
I have been trying various solutions, but no luck so far. Any help would be highly appreciated!

Related

QTextEdit clickable text

I have a log I have created with a simple [Add] text near each line which I want to be able to press and have it run a function that will know which line/text it has in this line.
I can also use QTextBrowser if needed for this.
My code:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(401, 308)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.chat_log = QtWidgets.QTextEdit(self.centralwidget)
self.chat_log.setGeometry(QtCore.QRect(10, 10, 381, 241))
self.chat_log.setReadOnly(True)
self.chat_log.setObjectName("chat_log")
MainWindow.setCentralWidget(self.centralwidget)
class MainFrame(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainFrame, self).__init__(parent)
self.setupUi(self)
def appending(self):
self.chat_log.append("Somethingsomething [Add]")
self.chat_log.append("Hello[Add]")
self.chat_log.append("What is up [Add]")
self.chat_log.append("Big boy [Add]")
if __name__ == "__main__":
app = QApplication(sys.argv)
form = MainFrame()
form.show()
form.appending()
app.exec_()
What I want is basically when someone pressed "[Add]" it will know which line it pressed and will print the text in that line
Say I pressed the first line it will then print("Somethingsomething")
You need to make your [Add] texts clickable, the easiest way to do so is using HTML markup, then you just need to identify the text you had been clicking on:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
class MyTextEdit(QtWidgets.QTextEdit):
def mousePressEvent(self, e):
self.link = self.anchorAt(e.pos())
def mouseReleaseEvent(self, e):
if self.link:
print(f"Clicked on {self.link}")
self.link = None
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(401, 308)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.chat_log = MyTextEdit(self.centralwidget)
self.chat_log.setGeometry(QtCore.QRect(10, 10, 381, 241))
self.chat_log.setReadOnly(True)
self.chat_log.setObjectName("chat_log")
MainWindow.setCentralWidget(self.centralwidget)
class MainFrame(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainFrame, self).__init__(parent)
self.setupUi(self)
def appending(self):
messages = ["Somethingsomething", "Hello", "What is up", "Big bo"]
for msg in messages:
self.chat_log.append(
f'<span>{msg}<a style="color: pink" href="{msg}">[Add]</a></span>'
)
if __name__ == "__main__":
app = QApplication(sys.argv)
form = MainFrame()
form.show()
form.appending()
app.exec_()
Out:
Clicked on Big bo
Clicked on Hello
Clicked on Somethingsomething

When I click the QpushButton, No change?

I use QT designer to design a page that contains two buttons, a start and an end, but when I click them, there is no response. I put them all in widgets, is that why?
I'm confused. When I click the start or end button,no Change!
PyQt5 When I click the QpushButton ,No change?
Is it because it's inside the widget?
My code is like this.
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(640, 480)
self.widget_6 = QtWidgets.QWidget(Form)
self.widget_6.setEnabled(True)
self.widget_6.setGeometry(QtCore.QRect(240, 250, 151, 68))
self.widget_6.setStyleSheet("background-color: rgb(230, 230, 230);")
self.widget_6.setObjectName("widget_6")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.widget_6)
self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.start_btn = QtWidgets.QPushButton(self.widget_6)
self.start_btn.setStyleSheet("")
self.start_btn.setObjectName("start_btn")
self.verticalLayout_4.addWidget(self.start_btn)
self.end_btn = QtWidgets.QPushButton(self.widget_6)
self.end_btn.setStyleSheet("")
self.end_btn.setObjectName("end_btn")
self.verticalLayout_4.addWidget(self.end_btn)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.start_btn.setText(_translate("Form", "start"))
self.end_btn.setText(_translate("Form", "end"))
import sys
from PyQt5.Qt import QApplication, QWidget
class Sorter(QWidget, Ui_Form):
"""
demo
"""
def __init__(self, parent=None, *args, **kwargs):
"""
init
"""
super(Sorter, self).__init__(parent, *args, **kwargs)
self.setupUi(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
myWin = Sorter()
myWin.show()
sys.exit(app.exec_())

pyqt5 drop down list with sub lists

I am trying to figure out how I can create a drop down list (currently using QComoboBox), with a few items, and when I hover my mouse/click on one of the options, it shows a sub list, containing a few more options.
I tried to search online but couldn't find anything that I could use.
Here an example of what I want to achieve (sorry for terrible quality, but I think it makes it clear what my goal is..)
Does any one have an idea of how to make a sub list inside a list?
Edit
After trying #eyllanesc suggestion I still having a problem:
I am using two files: one file that contains all the objects like buttons and such, and the other one that contains some functions and basically makes the GUI functional.
I defined this on my first file
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(751, 650)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.menuBtn=QtWidgets.QPushButton(self.centralwidget)
self.menuBtn.setGeometry(QtCore.QRect(100, 220, 100, 100))
self.productMenu=QtWidgets.QMenu(self.centralwidget)
self.menu1=self.productMenu.addMenu("options")
self.menu1.addAction("option 1")
self.menu2=self.productMenu.addMenu("option 2")
self.menu2.addAction("option 2a")
self.menu2.addAction("option 2b")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Test"))
self.menuBtn.setText(_translate("MainWindow", "Menu"))
And on the second file (the functional) I wrote this:
from PyQt5 import QtWidgets, QtCore, QtGui
from stackTest import Ui_MainWindow
import sys
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
super(ApplicationWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.productMenu.triggered.connect(lambda action: self.ui.menuBtn.setText(action.text("Hello!")))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
application = ApplicationWindow()
application.show()
sys.exit(app.exec_())
When I run the code, I can see the button, but when I click it nothing happens.
How can I make it run so when I push the button I'll get the menu.
One possible solution is to use a button (QPushButton, QToolButton, etc.) and establish a QMenu as I show below:
import sys
from PyQt5 import QtCore, QtWidgets
def create_menu(d, menu):
if isinstance(d, list):
for e in d:
create_menu(e, menu)
elif isinstance(d, dict):
for k, v in d.items():
sub_menu = QtWidgets.QMenu(k, menu)
menu.addMenu(sub_menu)
create_menu(v, sub_menu)
else:
action = menu.addAction(d)
action.setIconVisibleInMenu(False)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
d = ["1", "2", "3", {"4": ["5", "6", {"7": ["8", "9"]}]}, {"10": "11"}]
menu = QtWidgets.QMenu(self)
create_menu(d, menu)
button = QtWidgets.QPushButton()
button.setMenu(menu)
menu.triggered.connect(lambda action: button.setText(action.text()))
lay = QtWidgets.QHBoxLayout(self)
lay.addWidget(button)
lay.addStretch()
self.resize(640, 480)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
The code provided by the OP must add the QMenu to the QPushButton:
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from stackTest import Ui_MainWindow
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
super(ApplicationWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.menuBtn.setMenu(self.ui.productMenu)
self.ui.productMenu.triggered.connect(
lambda action: self.ui.menuBtn.setText(action.text())
)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
application = ApplicationWindow()
application.show()
sys.exit(app.exec_())

How to add some items or some pixmaps to the qgraphicscene?

I'm trying to make a puzzle game. My thought came from the 8-puzzle problem, so now I try to use the pyqt5. My opinion is that I choose a picture from my computer and then I try to use it. But when I try to upset the picture ,it comes some trouble.So I come here and look for help
since it comes to trouble so I simplify the code that just make the picture change into pieces. And now I just try them list on the qgraphicscene firstly, but I don't known why all of them stacked in the upper left corner, I just want them list in order which looks like the original picture, what should I do?
import sys
from vision import Ui_MainWindow
from PyQt5.QtWidgets import QMainWindow, QFileDialog
from PyQt5 import QtWidgets, QtGui, QtCore
from PIL import Image
class MyWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super(MyWindow, self).__init__()
self.setupUi(self)
self.item = []
self.if_opened = 0
self.dim = 3
self.upset.clicked.connect(self.make_upset)
def make_upset(self):
if self.image is None:
return
self.scene.clear()
self.showView.setScene(self.scene)
pixmap = QtGui.QPixmap(self.image)
x_side = self.image_file.size[0] / self.dim
y_side = self.image_file.size[1] / self.dim
count = 0
self.item.clear()
for j in range(self.dim):
for i in range(self.dim):
m = pixmap.copy(i * x_side, j * y_side, x_side, y_side)
self.item.append(QtWidgets.QGraphicsPixmapItem(m))
self.scene.addItem(self.item[count])
count = count + 1
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
myShow = MyWindow()
myShow.show()
sys.exit(app.exec_())
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1077, 741)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.upset = QtWidgets.QPushButton(self.centralwidget)
self.upset.setGeometry(QtCore.QRect(800, 210, 171, 51))
self.upset.setObjectName("upset")
self.showView = QtWidgets.QGraphicsView(self.centralwidget)
self.showView.setGeometry(QtCore.QRect(55, 38, 643, 623))
self.showView.setObjectName("showView")
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.upset.setText(_translate("MainWindow", "upset"))

Using PyQt4.QtGui.QMouseEvent in a QWidget

I am using a PyQt4.QMainWindow as my application interface, and I want to get the x and y coordinates of the mouse inside of a QWidget and set them continuously in 2 textBrowsers in the MainWindow.
The documentation for QWidget is here.
and the documentation for QMouseEvent is here.
Here is the code
from PyQt4 import QtGui
from PyQt4.QtGui import QApplication
import sys
class Ui_MainWindow(object):
def setupUI(self, MainWindow):
self.textBrowser_1 = QtGui.QTextBrowser(self.tab)
self.textBrowser_2 = QtGui.QTextBrowser(self.tab)
self.widget_1 = QtGui.QWidget(self.tab)
self.widget_1.setMouseTracking(True)
class MyMainScreen(QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.ui = Ui_MainWindow() # This is from a python export from QtDesigner
# There is a QWidget inside that is self.ui.widget_1
# and 2 textBrowsers, textBrowser_1 and textBrowser_2
# I want to populate these 2 textBrowsers with the current x,y
# coordinates.
if __name__ == "__main__":
app = QApplication(sys.argv)
mainscreen = MyMainScreen()
mainscreen.show()
app.exec_()
When you apply setMouseTracking it only applies to that widget, and not to your children, so you must manually, in the next solution:
def setMouseTracking(self, flag):
def recursive_set(parent):
for child in parent.findChildren(QtCore.QWidget):
child.setMouseTracking(flag)
recursive_set(child)
QtGui.QWidget.setMouseTracking(self, flag)
recursive_set(self)
complete code:
from PyQt4 import QtCore
from PyQt4 import QtGui
from PyQt4.QtGui import QApplication, QMainWindow
import sys
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.resize(800, 132)
self.centralwidget = QtGui.QWidget(MainWindow)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.textBrowser_1 = QtGui.QTextBrowser(self.centralwidget)
self.horizontalLayout.addWidget(self.textBrowser_1)
self.textBrowser_2 = QtGui.QTextBrowser(self.centralwidget)
self.horizontalLayout.addWidget(self.textBrowser_2)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
MainWindow.setStatusBar(self.statusbar)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
class MyMainScreen(QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.ui = Ui_MainWindow() # This is from a python export from QtDesigner
self.ui.setupUi(self)
self.setMouseTracking(True)
self.ui.textBrowser_1.setMouseTracking(True)
self.ui.textBrowser_2.setMouseTracking(True)
self.ui.menubar.setMouseTracking(True)
self.ui.statusbar.setMouseTracking(True)
def setMouseTracking(self, flag):
def recursive_set(parent):
for child in parent.findChildren(QtCore.QWidget):
child.setMouseTracking(flag)
recursive_set(child)
QtGui.QWidget.setMouseTracking(self, flag)
recursive_set(self)
def mouseMoveEvent(self, event):
pos = event.pos()
self.ui.textBrowser_1.append(str(pos.x()))
self.ui.textBrowser_2.append(str(pos.y()))
QtGui.QMainWindow.mouseMoveEvent(self, event)
if __name__ == "__main__":
app = QApplication(sys.argv)
mainscreen = MyMainScreen()
mainscreen.show()
app.exec_()
This is my output:

Categories

Resources