最近各种实验一直在使用PyQT进行GUI编程,网上教程博客很多,但是良莠不齐,在此总结一下用到的组件。
from PyQt5.QtWidgets import QMessageBox
class Message(QtWidgets.QWidget):
def __init__(self):
super(Message, self).__init__()
def alert(self, msg):
reply = QMessageBox.information(self,
"警告",
msg,
QMessageBox.Yes | QMessageBox.No)
# 调用
myshow = Message()
myshow.alert("Your Message Here")
from PyQt5.QtWidgets import QFileDialog
fileName, filetype = QFileDialog.getOpenFileName(self,
"选取文件",
"./",
"PNG Files (*.png);;JPG Files (*.jpg)")
self
是表示所在的父面板
可以使用正则*
匹配用户可选的文件类型
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class MyPyQT_Form(QtWidgets.QWidget, Ui_Form):
def __init__(self):
super(MyPyQT_Form, self).__init__()
self.setupUi(self)
self.pushButton_start.clicked.connect(self.start)
self.pushButton_end.clicked.connect(self.end)
def start(self):
self.timer_id = self.startTimer(1000, timerType=QtCore.Qt.VeryCoarseTimer)
self.pushButton_start.setEnabled(False)
self.pushButton_end.setEnabled(True)
def end(self):
self.signal = False
if self.timer_id:
self.killTimer(self.timer_id)
self.timer_id = 0
self.pushButton_start.setEnabled(True)
self.pushButton_end.setEnabled(False)
详见参考链接
主要解决一个问题,原始错误显示找不到了,大概就是,不能在非GUI的线程中创建或操作GUI组件
意思就是说,在GUI中使用threading.Thread(target=func)
,执行的func
函数中,无法操作GUI组件。因为threading.Thread()
不是GUI的线程,只有Qthread
是GUI的线程,因此需要使用Qthread
代替threading.Thread()
# ......
self.thread = Thread()
self.thread.start()
self.thread.trigger.connect(self.output)
def output(self):
# .......
# ......
class Thread(QThread):
"""docstring for Thread"""
trigger = pyqtSignal()
def __init__(self):
super(Thread, self).__init__()
def run(self):
os.system("python run_mrc.py")
self.trigger.emit()
参考链接,讲的非常好
参考上一篇博客[Python技能] QtWebView + Jinja2 + JavaScript + MySQL
主要是在嵌入的网页上,如果用户点击了网页上的按钮,则产生Js时间,然后将信号传回Python进行下一步响应。
下面代码是创建一个传递给Js的对象,用于信号交互
# -*- coding: utf-8 -*-
from PyQt5.QtCore import *
import time
import random
from concurrent.futures import ThreadPoolExecutor
class MyObjectCls(QObject):
sigSetParentWindowTitle = pyqtSignal(str)
def __init__(self, parent=None):
self.pool = ThreadPoolExecutor(10)
QObject.__init__(self, parent)
# 注册信息
def enroll(self, user_id, friend_id, ):
self.user_id = user_id
self.friend_id = friend_id
@pyqtSlot(str)
def putMessage(self, msg):
# 线程池使用
self.pool.submit(self.write_messages, msg)
def write_messages(self, msg):
cur_time = time.strftime('%Y-%m-%d', time.localtime(time.time()))
print(cur_time)
下面在主面板创建并注册上述代码中的对象
# ......
self.view = QWebEngineView(self)
self.view.setGeometry(QtCore.QRect(0, 0, 700, 600))
# 绝对地址,否则无法正常显示
self.view.setHtml(self.get_chat_msg(), baseUrl=QtCore.QUrl.fromLocalFile(os.path.abspath('templates/chat.html')))
# 注册
self.channel = QWebChannel(self.view.page())
self.my_project = MyObjectCls(self.view)
self.my_project.enroll(self.config["user_id"], self.friend["user_id"])
self.channel.registerObject("MyObject", self.my_project)
self.view.page().setWebChannel(self.channel)
# ......
下面是HTML中的js代码
$(function(){
$(".mui-btn").click(function () {
// 事件代码
// 向python进行数据交互,传递数据msg
new QWebChannel(qt.webChannelTransport, function(channel) {
var my_object = channel.objects.MyObject;
my_object.putMessage(msg);
});
// 事件代码
});
});
将以下代码保存到文件QCodeEditor.py
,使用from QCodeEditor import QCodeEditor
,代替本来的QTextEdit
即可
#!/usr/bin/python3
# QcodeEditor.py by acbetter.
# -*- coding: utf-8 -*-
from PyQt5.QtCore import Qt, QRect, QSize
from PyQt5.QtWidgets import QWidget, QPlainTextEdit, QTextEdit
from PyQt5.QtGui import QColor, QPainter, QTextFormat
class QLineNumberArea(QWidget):
def __init__(self, editor):
super().__init__(editor)
self.codeEditor = editor
def sizeHint(self):
return QSize(self.editor.lineNumberAreaWidth(), 0)
def paintEvent(self, event):
self.codeEditor.lineNumberAreaPaintEvent(event)
class QCodeEditor(QPlainTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.lineNumberArea = QLineNumberArea(self)
self.blockCountChanged.connect(self.updateLineNumberAreaWidth)
self.updateRequest.connect(self.updateLineNumberArea)
self.cursorPositionChanged.connect(self.highlightCurrentLine)
self.updateLineNumberAreaWidth(0)
def lineNumberAreaWidth(self):
digits = 1
max_value = max(1, self.blockCount())
while max_value >= 10:
max_value /= 10
digits += 1
space = 3 + self.fontMetrics().width('9') * digits
return space
def updateLineNumberAreaWidth(self, _):
self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0)
def updateLineNumberArea(self, rect, dy):
if dy:
self.lineNumberArea.scroll(0, dy)
else:
self.lineNumberArea.update(0, rect.y(), self.lineNumberArea.width(), rect.height())
if rect.contains(self.viewport().rect()):
self.updateLineNumberAreaWidth(0)
def resizeEvent(self, event):
super().resizeEvent(event)
cr = self.contentsRect()
self.lineNumberArea.setGeometry(QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height()))
def highlightCurrentLine(self):
extraSelections = []
if not self.isReadOnly():
selection = QTextEdit.ExtraSelection()
lineColor = QColor(Qt.yellow).lighter(160)
selection.format.setBackground(lineColor)
selection.format.setProperty(QTextFormat.FullWidthSelection, True)
selection.cursor = self.textCursor()
selection.cursor.clearSelection()
extraSelections.append(selection)
self.setExtraSelections(extraSelections)
def lineNumberAreaPaintEvent(self, event):
painter = QPainter(self.lineNumberArea)
painter.fillRect(event.rect(), Qt.lightGray)
block = self.firstVisibleBlock()
blockNumber = block.blockNumber()
top = self.blockBoundingGeometry(block).translated(self.contentOffset()).top()
bottom = top + self.blockBoundingRect(block).height()
# Just to make sure I use the right font
height = self.fontMetrics().height()
while block.isValid() and (top <= event.rect().bottom()):
if block.isVisible() and (bottom >= event.rect().top()):
number = str(blockNumber + 1)
painter.setPen(Qt.black)
painter.drawText(0, top, self.lineNumberArea.width(), height, Qt.AlignRight, number)
block = block.next()
top = bottom
bottom = top + self.blockBoundingRect(block).height()
blockNumber += 1
if __name__ == '__main__':
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
codeEditor = QCodeEditor()
codeEditor.show()
sys.exit(app.exec_())
参考StackOverflow Create text area (textEdit) with line number in PyQt
import sys
import os
import time
#from myUI import Ui_MainWindow #导入生成myUI.py里生成的类
from tab import Ui_testTAB
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
#打开gif文件
movie = QtGui.QMovie("./icon/watch.gif")
#设置cacheMode为CacheAll时表示gif无限循环,注意此时loopCount()返回-1
movie.setCacheMode(QtGui.QMovie.CacheAll)
#播放速度
movie.setSpeed(100)
#self.movie_screen是在qt designer里定义的一个QLabel对象的对象名,将gif显示在label上
self.movie_screen.setMovie(movie)
#开始播放,对应的是movie.start()
movie.start()
StyleSheet
设置为border:none