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"))
Related
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
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!
Evening. I am having a bit of a hard time both understanding QTimer and how it works as well as getting the below code to work. As much as I hate copy/pasting, I just cannot figure it out. The goal of this is to run the program for 15 seconds and then exit out completely. Everything else works, but when I try to integrate QTimer to count how many seconds have passed, it does nothing or just simply does not work regardless of the variations I try. Below is the latest code:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QMovie
from PyQt5.QtCore import QTimer
import winsound
import time
import sys
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(321, 249)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(0, 0, 320, 248))
self.label.setFrameShape(QtWidgets.QFrame.Box)
self.label.setOpenExternalLinks(False)
self.label.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
self.label.setObjectName("label")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
#Plays the movie in the Label
movie = QMovie("giphy.gif")
self.label.setMovie(movie)
movie.start()
#Plays the sound with the movie
winsound.PlaySound("magicwrd.wav", winsound.SND_ASYNC|winsound.SND_LOOP)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
#Borrowed and modified from here: https://stackoverflow.com/questions/46656634/pyqt5-qtimer-count-until-specific-seconds
#Goal is to run the application for 15 seconds and then exit out completely.
def start_timer(self, slot, count=1, interval=1000):
counter = 0
def handler():
nonlocal counter
counter += 1
slot(counter)
if counter >= count:
timer.stop()
timer.deleteLater()
timer = QtCore.QTimer()
timer.timeout.connect(handler)
timer.start(interval)
def timer_func(self, count):
if count >= 5:
sys.exit(app.exec_())
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
Ui_MainWindow.start_timer(Ui_MainWindow.timer_func, 5)
app.exec_()
If you want to finish the application in T seconds then you must use a QTimer::singleShot() so that when it is triggered then QCoreApplication::quit() is invoked:
QtCore.QTimer.singleShot(T * 1000, QtCore.QCoreApplication.quit)
In the example that you link, it has another objective: to print some information every T seconds and after repeating K times the application is closed, and therefore uses a complicated logic that you do not need.
Considering the above and the PyQt5 recommendation, the solution is:
import sys
import winsound
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(321, 249)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(0, 0, 320, 248))
self.label.setFrameShape(QtWidgets.QFrame.Box)
self.label.setOpenExternalLinks(False)
self.label.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
self.label.setObjectName("label")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
# Plays the movie in the Label
movie = QtGui.QMovie("giphy.gif")
self.label.setMovie(movie)
movie.start()
# Plays the sound with the movie
winsound.PlaySound("magicwrd.wav", winsound.SND_ASYNC | winsound.SND_LOOP)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
QtCore.QTimer.singleShot(15 * 1000, QtCore.QCoreApplication.quit)
sys.exit(app.exec_())
It is not a duplicate! I didn't want to make title really long, so it's short version may seem as a duplicate. The problem is a little bit bigger than in the title.
Environment: I'm trying to build painting app using PyQt5 and Qt-Designer. I've got three files in my project: main.py, slider.py, ui.py(UI from Qt-Designer generated by pyuic).
What do I need: I need to change App's brush size(self.variable) every time Slider value changes.
The problem itself: App Class inherits Ui_MainWindow Class from the file that I can't edit(it is generated every time). Ui_MainWindow sets Slider Class as its attribute. So basically Slider is App's attribute, and I need to change App's variable "canvas" while being in Slider Class.
I don't know how to access outer class variable in inner class method. Especially when I can't edit ui.py, so I could call Slider(self) instead of Slider(self.sidebar).
main.py
import sys
from PyQt5 import uic
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from ui import Ui_MainWindow
class App(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
if __name__ == '__main__':
application = QApplication(sys.argv)
example = App()
example.show()
sys.exit(application.exec_())
slider.py
from PyQt5 import uic
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from functools import partial
import inspect
class Slider(QSlider):
def __init__(self, parent=None):
super().__init__(parent)
self.valueChanged.connect(self.valueChange)
self.setMinimum(8)
self.setMaximum(64)
self.setTickInterval(8)
def valueChange(self):
pass
# Here I need to change App.canvas, have no idea how to do it
ui.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'main.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(912, 715)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setObjectName("horizontalLayout")
self.sidebar = QtWidgets.QWidget(self.centralwidget)
self.sidebar.setMinimumSize(QtCore.QSize(388, 0))
self.sidebar.setAutoFillBackground(True)
self.sidebar.setObjectName("sidebar")
self.clearButton = QtWidgets.QPushButton(self.sidebar)
self.clearButton.setGeometry(QtCore.QRect(20, 30, 91, 41))
self.clearButton.setObjectName("clearButton")
# This is where Slider is called
# The file is generated so I can't edit it
self.brushSizeSlider = Slider(self.sidebar)
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
self.brushSizeSlider.setGeometry(QtCore.QRect(20, 120, 160, 22))
self.brushSizeSlider.setOrientation(QtCore.Qt.Horizontal)
self.brushSizeSlider.setObjectName("brushSizeSlider")
self.brushSizeLabel = QtWidgets.QLabel(self.sidebar)
self.brushSizeLabel.setGeometry(QtCore.QRect(20, 90, 101, 16))
self.brushSizeLabel.setObjectName("brushSizeLabel")
self.brushColorDial = QtWidgets.QDial(self.sidebar)
self.brushColorDial.setGeometry(QtCore.QRect(20, 180, 50, 64))
self.brushColorDial.setObjectName("brushColorDial")
self.brushColorLabel = QtWidgets.QLabel(self.sidebar)
self.brushColorLabel.setGeometry(QtCore.QRect(20, 160, 101, 16))
self.brushColorLabel.setObjectName("brushColorLabel")
self.horizontalLayout.addWidget(self.sidebar)
self.canvas = Canvas(self.centralwidget)
self.canvas.setMinimumSize(QtCore.QSize(500, 500))
self.canvas.setMaximumSize(QtCore.QSize(5000, 5000))
self.canvas.setBaseSize(QtCore.QSize(500, 500))
self.canvas.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
self.canvas.setAutoFillBackground(True)
self.canvas.setStyleSheet("canvas{background-color: rgb(70, 70, 50);}")
self.canvas.setObjectName("canvas")
self.horizontalLayout.addWidget(self.canvas)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.clearButton.setText(_translate("MainWindow", "Clear canvas"))
self.brushSizeLabel.setText(_translate("MainWindow", "Current brush size:"))
self.brushColorLabel.setText(_translate("MainWindow", "Current brush color:"))
from canvas import Canvas
from slider import Slider
I have a main window which creates a second window when a button is pressed. I have two problems that occur but for now I will focus on the first one: I cannot get it to completely close the old window when I close it. It closes it visually but the window is still running in the background. To illustrate this I put in a counter. Below is generic code which illustrates this issue.
Here is my dialog window:
from PyQt5 import QtCore, QtGui, QtWidgets
from form_test import Ui_Form
class formTest(QtWidgets.QWidget, Ui_Form):
def __init__(self):
QtWidgets.QWidget.__init__(self)
flags = QtCore.Qt.Drawer | QtCore.Qt.WindowStaysOnTopHint
self.setWindowFlags(flags)
self.setupUi(self)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(507, 305)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.btnOpenForm = QtWidgets.QPushButton(self.centralwidget)
self.btnOpenForm.setGeometry(QtCore.QRect(170, 30, 93, 28))
self.btnCloseForm = QtWidgets.QPushButton(self.centralwidget)
self.btnCloseForm.setGeometry(QtCore.QRect(170, 160, 93, 28))
MainWindow.setCentralWidget(self.centralwidget)
self.btnOpenForm.clicked.connect(self.openClicked)
self.btnCloseForm.clicked.connect(self.closeClicked)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.btnOpenForm.setText(_translate("MainWindow", "Open Form"))
self.btnCloseForm.setText(_translate("MainWindow", "Close Form"))
def openClicked(self):
print('open')
self.popForm = formTest()
self.popForm.show()
def closeClicked(self):
print('close')
self.popForm.close()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Here is my spawning windows code (form_test.py):
from PyQt5 import QtCore, QtGui, QtWidgets
import time, threading
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 300)
self.pushButton = QtWidgets.QPushButton(Form)
self.pushButton.setGeometry(QtCore.QRect(190, 170, 93, 28))
self.pushButton.setObjectName("pushButton")
self.pushButton.clicked.connect(self.pushButtonClicked)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
self.loopThread = threading.Thread(target = self.looping)
self.loopThread.daemon = True
self.loopThread.start()
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.pushButton.setText(_translate("Form", "PushButton"))
def pushButtonClicked(self):
print("clicked")
def looping(self):
count = 0
while(True):
print('looping... ' + str(count))
count = count + 1
time.sleep(1)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())
When I close the second window it is still running in memory. When I try to open it again another one begins running and then I have two running. Is there a different window I should use which will destroy all memory when it is closed? The second issue I am having is which my actual code (not this generic code) it causes a crash when I try to launch a second time. That issue may go away with the fixing of this issue and since I am not able to share my code online I have to stay as generic as possible for now so I am hoping to solve this issue first and maybe get resolution too.
PLEASE help ... I've worked on this FAR too long!!! Thanks, in advance, for any assistance on this.