I am trying to set a custom property of an image inserted into a QTextEdit. I have the following example code which sets then outputs the value of the property to the terminal:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class TestEditor(QWidget):
def __init__(self):
QWidget.__init__(self)
layout = QVBoxLayout()
self.setLayout(layout)
self.layout().setSpacing(0)
self.layout().setContentsMargins(0, 0, 0, 0)
self.textEdit = QTextEdit()
self.layout().addWidget(self.textEdit)
document = self.textEdit.document()
cursor = QTextCursor(document)
cursor.insertImage("./testimage.png")
f = cursor.charFormat()
print(f)
prop_id = 0x100000 + 1
f.setProperty(prop_id, 100)
print(f.intProperty(prop_id))
print('------')
block = document.firstBlock()
while block.length() > 0:
print(block)
it = block.begin()
while not it.atEnd():
f = it.fragment()
fmt = f.charFormat()
print(fmt)
print(fmt.intProperty(prop_id))
it += 1
block = block.next()
class TestWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
self.initUi()
def initUi(self):
layout = QVBoxLayout()
layout.addWidget(HextEditor())
self.setLayout(layout)
self.layout().setSpacing(0)
self.layout().setContentsMargins(0, 0, 0, 0)
self.setWindowTitle('button tooltip')
self.show()
def main():
app = QApplication(sys.argv)
window = TestWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The program results in an output of:
<PyQt5.QtGui.QTextCharFormat object at 0x107109ba8>
100
------
<PyQt5.QtGui.QTextBlock object at 0x105448318>
<PyQt5.QtGui.QTextCharFormat object at 0x107109ba8>
0
Note that the second time the value is gotten it has a value of 0 rather than 100. It even appears to be the same instance of a QTextCharFormat. How would I accomplish something like this? Am I missing something simple here?
I solved this by saving the range of the inserted image, selecting it, and using QTextCursor.setCharFormat() to save the changes:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class TestEditor(QWidget):
def __init__(self):
QWidget.__init__(self)
layout = QVBoxLayout()
self.setLayout(layout)
self.layout().setSpacing(0)
self.layout().setContentsMargins(0, 0, 0, 0)
self.textEdit = QTextEdit()
self.layout().addWidget(self.textEdit)
document = self.textEdit.document()
cursor = QTextCursor(document)
# Save the position of the beginning and end of the inserted image
p1 = cursor.position()
cursor.insertImage("./testimage.png")
p2 = cursor.position()
f = cursor.charFormat()
print(f)
prop_id = 0x100000 + 1
f.setProperty(prop_id, 100)
# Select the inserted fragment and apply format
cursor.setPosition(p1)
cursor.setPosition(p2, QTextCursor.KeepAnchor)
cursor.setCharFormat(f)
print(f.intProperty(prop_id))
print('------')
block = document.firstBlock()
while block.length() > 0:
print(block)
it = block.begin()
while not it.atEnd():
f = it.fragment()
fmt = f.charFormat()
print(fmt)
print(fmt.intProperty(prop_id))
it += 1
block = block.next()
class TestWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
self.initUi()
def initUi(self):
layout = QVBoxLayout()
layout.addWidget(TestEditor())
self.setLayout(layout)
self.layout().setSpacing(0)
self.layout().setContentsMargins(0, 0, 0, 0)
self.setWindowTitle('button tooltip')
self.show()
def main():
app = QApplication(sys.argv)
window = TestWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Related
I am trying to create a basic 25 key keyboard in pyqt, I have laid out the 15 white keys but am struggling with how to add the 10 remaining black keys,
This is how I made my keys
from PyQt5.QtWidgets import QApplication, QPushButton
app = QApplication([])
top_win = QWidget()
set_color(top_win, Qt.cyan)
top_win.setAutoFillBackground(True)
top_win.show()
top_win.resize(1920,1080)
top_win.setWindowTitle("Synth-01")
top_vlayout = QVBoxLayout()
top_win.setLayout(top_vlayout)
keyboard = QWidget()
keyboard.setMaximumWidth(1410)
top_vlayout.addWidget(keyboard)
keyboard_layout = QHBoxLayout()
keyboard.setAutoFillBackground(True)
keyboard.setLayout(keyboard_layout)
for i in range(15):
name = "key_" + str(i)
name = QPushButton()
name.setMaximumWidth(94)
name.setMaximumHeight(349)
keyboard_layout.addWidget(name)
I now want to add the black keys inbetween like this
In this case, it is most preferable to use QGraphicsScene with QGraphicsItem, for this case I will use svg:
from PyQt5 import QtCore, QtGui, QtWidgets, QtSvg
class PianoKey(QtWidgets.QGraphicsRectItem):
def __init__(self, black=False, rect = QtCore.QRectF(), parent=None):
super(PianoKey, self).__init__(rect, parent)
self.m_pressed = False
self.m_selectedBrush = QtGui.QBrush()
self.m_brush = QtGui.QBrush(QtCore.Qt.black) if black else QtGui.QBrush(QtCore.Qt.white)
self.m_black = black
def setPressedBrush(self, brush):
self.m_selectedBrush = brush
def paint(self, painter, option, widget):
rendered = QtSvg.QSvgRenderer("key.svg")
black_pen = QtGui.QPen(QtCore.Qt.black, 1)
gray_pen = QtGui.QPen(QtGui.QBrush(QtCore.Qt.gray), 1,
QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
if self.m_pressed:
if self.m_selectedBrush.style() != QtCore.Qt.NoBrush:
painter.setBrush(self.m_selectedBrush)
else:
painter.setBrush(QtWidgets.QApplication.palette().highlight())
else:
painter.setBrush(self.m_brush);
painter.setPen(black_pen)
painter.drawRoundedRect(self.rect(), 15, 15, QtCore.Qt.RelativeSize)
if self.m_black:
rendered.render(painter, self.rect())
else:
points = [
QtCore.QPointF(self.rect().left()+1.5, self.rect().bottom()-1),
QtCore.QPointF(self.rect().right()-1, self.rect().bottom()-1),
QtCore.QPointF(self.rect().right()-1, self.rect().top()+1)
]
painter.setPen(gray_pen)
painter.drawPolyline(QtGui.QPolygonF(points))
def mousePressEvent(self, event):
self.m_pressed = True
self.update()
super(PianoKey, self).mousePressEvent(event)
event.accept()
def mouseReleaseEvent(self, event):
self.m_pressed = False
self.update()
super(PianoKey, self).mouseReleaseEvent(event)
KEYWIDTH, KEYHEIGHT = 18, 72
class PianoKeyBoard(QtWidgets.QGraphicsView):
def __init__(self, num_octaves=2, parent=None):
super(PianoKeyBoard, self).__init__(parent)
self.initialize()
self.m_numOctaves = num_octaves
scene = QtWidgets.QGraphicsScene(QtCore.QRectF(0, 0, KEYWIDTH * self.m_numOctaves * 7, KEYHEIGHT), self)
self.setScene(scene)
numkeys = self.m_numOctaves * 12
for i in range(numkeys):
octave = i//12*7
j = i % 12
if j >= 5: j += 1
if j % 2 == 0:
x = (octave + j/2)*KEYWIDTH
key = PianoKey(rect=QtCore.QRectF(x, 0, KEYWIDTH, KEYHEIGHT), black=False)
else:
x = (octave + j//2) * KEYWIDTH + KEYWIDTH * 6//10 + 1
key = PianoKey(rect=QtCore.QRectF(x, 0, KEYWIDTH * 8//10 - 1, KEYHEIGHT * 6//10 ), black=True)
key.setZValue(1)
key.setPressedBrush(QtWidgets.QApplication.palette().highlight())
self.scene().addItem(key)
def initialize(self):
self.setAttribute(QtCore.Qt.WA_InputMethodEnabled, False)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setCacheMode(QtWidgets.QGraphicsView.CacheBackground)
self.setViewportUpdateMode(QtWidgets.QGraphicsView.MinimalViewportUpdate)
self.setRenderHints(QtGui.QPainter.Antialiasing|
QtGui.QPainter.TextAntialiasing |
QtGui.QPainter.SmoothPixmapTransform)
self.setOptimizationFlag(QtWidgets.QGraphicsView.DontClipPainter, True)
self.setOptimizationFlag(QtWidgets.QGraphicsView.DontSavePainterState, True)
self.setOptimizationFlag(QtWidgets.QGraphicsView.DontAdjustForAntialiasing, True)
self.setBackgroundBrush(QtWidgets.QApplication.palette().base())
def resizeEvent(self, event):
super(PianoKeyBoard, self).resizeEvent(event)
self.fitInView(self.scene().sceneRect(), QtCore.Qt.KeepAspectRatio)
def sizeHint(self):
return self.mapFromScene(self.sceneRect()).boundingRect().size()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('fusion')
w = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(w)
lay.addWidget(QtWidgets.QLabel("Piano Keyboard", alignment=QtCore.Qt.AlignCenter))
lay.addWidget(PianoKeyBoard())
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
The complete code + key.svg can be found on this link
I`m playing with PyQt, and trying to add two values (numbers) together.
When I try do display the output for this, I just get this message:
Picture here
my code:
labelwidth = QLabel('Width in meter', self)
self.width = QLineEdit(self)
self.width.move (100,0)
labelwidth.move (5,0)
labeldepth = QLabel('Depth in meter', self)
self.depth = QLineEdit(self)
self.depth.move (100,50)
labeldepth.move (5,50)
#Send data
btn = QPushButton('Send', self)
btn.clicked.connect(self.send_data)
btn.move (100, 100)
self.show()
def send_data(self):
width_to_str = str(self.width)
dept_to_str = str(self.depth)
kvm = width_to_int + dept_to_int
labelkvm = QLabel(kvm, self)
labelkvm.move = (200, 100)
QMessageBox.about(self, "Sendt", kvm)
self.show()
I have tried to convert it to int before it summarize the number.
How can I solve this?
Try it:
import sys
import pandas as pd
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class MainWindow(QWidget):
def __init__(self):
super().__init__()
labelwidth = QLabel('Width in meter', self)
self.width = QLineEdit(self)
self.width.move (100,0)
labelwidth.move (5,0)
labeldepth = QLabel('Depth in meter', self)
self.depth = QLineEdit(self)
self.depth.move (100,50)
labeldepth.move (5,50)
#Send data
btn = QPushButton('Send', self)
btn.clicked.connect(self.send_data)
btn.move (100, 100)
self.show()
def send_data(self):
width_to_str = int(self.width.text()) # <---
dept_to_str = int(self.depth.text()) # <---
kvm = str(width_to_str + dept_to_str) # <---
labelkvm = QLabel(kvm, self)
labelkvm.move = (200, 100)
QMessageBox.about(self, "Sendt", kvm)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
mainwindow = MainWindow()
mainwindow.show()
sys.exit(app.exec_())
I have created a widget with QLineEdit and QLabel, I want to get input from QlineEdit and display it with QLabel. I have used Signal and Slot connection, I do not know what I do wrong, but it is not working correctly. I would like to get both values from QLineEdit and later show it.
Current window
what I want?
Code:
import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class WinDialog(QtWidgets.QDialog):
currenttextedited = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super(WinDialog, self).__init__(parent)
self.setGeometry(300,300,350,300)
self.setWindowTitle("Signal & Slot")
self.propertyWidget = PropertyWidget()
section_lay = QtWidgets.QHBoxLayout()
section_label = QtWidgets.QLabel("Name: ")
section_edit = QtWidgets.QLineEdit('')
length_lay = QtWidgets.QHBoxLayout()
length_label = QtWidgets.QLabel("Input a number: L = ")
self.length_edit = QtWidgets.QLineEdit('1000')
self.length_edit.setInputMask("999999")
self.length_edit.setFocus(True)
thick_lay = QtWidgets.QHBoxLayout()
thick_label = QtWidgets.QLabel("Input a text: T = ")
thick_edit = QtWidgets.QLineEdit('')
section_lay.addWidget(section_label)
section_lay.addWidget(section_edit)
length_lay.addWidget(length_label)
length_lay.addWidget(self.length_edit)
length_lay.addStretch()
thick_lay.addWidget(thick_label)
thick_lay.addWidget(thick_edit)
thick_lay.addStretch()
VB_lay = QtWidgets.QVBoxLayout()
VB_lay.addStretch()
VB_lay.addLayout(length_lay)
VB_lay.addLayout(thick_lay)
VB_lay.addStretch()
buttonBox = QtWidgets.QDialogButtonBox()
buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel
|QtWidgets.QDialogButtonBox.Ok)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
grid = QtWidgets.QGridLayout(self)
grid.addLayout(section_lay, 0, 0, 1, 2)
grid.addLayout(VB_lay, 1, 0)
grid.addWidget(self.propertyWidget, 2, 0)
grid.addWidget(buttonBox, 3, 0, 1, 2)
self.length_edit.textEdited.connect(self.textchanged)
def textchanged(self, text):
print(text)
self.currenttextedited.emit(text)
class PropertyWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(PropertyWidget, self).__init__(parent)
HB_lay = QtWidgets.QHBoxLayout(self)
self.Displaylabel = QtWidgets.QLabel('')
HB_lay.addWidget(self.Displaylabel)
HB_lay.addStretch()
#QtCore.pyqtSlot(int)
def Display(self, text):
try:
L_Display = int(text)
T_Display = int(text)
fmt = "L = {}mm\nT = {}mm"
self.Displaylabel.setText(fmt.format(L_Display, T_Display))
except ValueError:
print("Error")
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = WinDialog()
w.show()
sys.exit(app.exec_())
according to samples in the image you want to show different texts but you are converting the same number to whole: L_Display = int(text) and T_Display = int(text) so how do you expect to show 2 different texts?, obviously the function display needs 2 entries (2 different entries to self plus I have changed to lowercase since it is recommended that the functions have a lowercase name).
Now the logic is as follows: if any of the texts of length_edit or thick_edit changes then you must call display() passing the new texts. So the solution is to use a slot that connects to the textEdited signals of both QLineEdits and in it obtain the text and pass the texts.
Finally I see that you want the QLineEdits receive only numbers so one option is to use a QIntValidator so that only numbers are acceptable (another better option is to use QSpinBox instead of QLineEdit)
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class WinDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(WinDialog, self).__init__(parent)
self.setGeometry(300,300,350,300)
self.setWindowTitle("Signal & Slot")
self.propertyWidget = PropertyWidget()
section_lay = QtWidgets.QHBoxLayout()
section_label = QtWidgets.QLabel("Name: ")
section_edit = QtWidgets.QLineEdit('')
length_lay = QtWidgets.QHBoxLayout()
length_label = QtWidgets.QLabel("Input a number: L = ")
self.length_edit = QtWidgets.QLineEdit()
self.length_edit.setFocus(True)
val_lenght = QtGui.QIntValidator(0, 100000, self.length_edit)
self.length_edit.setValidator(val_lenght)
thick_lay = QtWidgets.QHBoxLayout()
thick_label = QtWidgets.QLabel("Input a text: T = ")
self.thick_edit = QtWidgets.QLineEdit()
val_thick = QtGui.QIntValidator(0, 100000, self.thick_edit)
self.thick_edit.setValidator(val_thick)
section_lay.addWidget(section_label)
section_lay.addWidget(section_edit)
length_lay.addWidget(length_label)
length_lay.addWidget(self.length_edit)
length_lay.addStretch()
thick_lay.addWidget(thick_label)
thick_lay.addWidget(self.thick_edit)
thick_lay.addStretch()
VB_lay = QtWidgets.QVBoxLayout()
VB_lay.addStretch()
VB_lay.addLayout(length_lay)
VB_lay.addLayout(thick_lay)
VB_lay.addStretch()
buttonBox = QtWidgets.QDialogButtonBox()
buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel
| QtWidgets.QDialogButtonBox.Ok)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
grid = QtWidgets.QGridLayout(self)
grid.addLayout(section_lay, 0, 0, 1, 2)
grid.addLayout(VB_lay, 1, 0)
grid.addWidget(self.propertyWidget, 2, 0)
grid.addWidget(buttonBox, 3, 0, 1, 2)
self.length_edit.textEdited.connect(self.onTextEdited)
self.thick_edit.textEdited.connect(self.onTextEdited)
def onTextEdited(self):
l = self.length_edit.text()
t = self.thick_edit.text()
self.propertyWidget.display(l, t)
class PropertyWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(PropertyWidget, self).__init__(parent)
HB_lay = QtWidgets.QHBoxLayout(self)
self.Displaylabel = QtWidgets.QLabel('')
HB_lay.addWidget(self.Displaylabel)
HB_lay.addStretch()
def display(self, l, t):
try:
L_Display = int(l)
T_Display = int(t)
fmt = "L = {}mm\nT = {}mm"
self.Displaylabel.setText(fmt.format(L_Display, T_Display))
except ValueError:
self.Displaylabel.clear()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = WinDialog()
w.show()
sys.exit(app.exec_())
What I'm trying to do is add splitter to a QGridLayout in order to resize the layout with the mouse. So for instance with this :
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class SurfViewer(QMainWindow):
def __init__(self, parent=None):
super(SurfViewer, self).__init__()
self.parent = parent
self.setFixedWidth(300)
self.setFixedHeight(100)
self.wid = QWidget()
self.setCentralWidget(self.wid)
self.grid = QGridLayout()
l_a = QLabel('A')
l_b = QLabel('B')
l_c = QLabel('C')
l_d = QLabel('D')
l_e = QLabel('E')
l_f = QLabel('F')
l_g = QLabel('G')
l_h = QLabel('H')
l_i = QLabel('I')
self.grid.addWidget(l_a, 0, 0)
self.grid.addWidget(l_b, 0, 1)
self.grid.addWidget(l_c, 0, 2)
self.grid.addWidget(l_d, 1, 0)
self.grid.addWidget(l_e, 1, 1)
self.grid.addWidget(l_f, 1, 2)
self.grid.addWidget(l_g, 2, 0)
self.grid.addWidget(l_h, 2, 1)
self.grid.addWidget(l_i, 2, 2)
self.wid.setLayout(self.grid)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = SurfViewer(app)
ex.setWindowTitle('window')
ex.show()
sys.exit(app.exec_( ))
I get this:
What I would like is instead of the colored line, have the possibility to click and drag vertically (for green lines) and horizontally (for red lines) the grid borders.
I tried something with QSplitter directly, but I end up with:
The Horizontal splits are okay, but the vertical ones are not aligned any more:
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class SurfViewer(QMainWindow):
def __init__(self, parent=None):
super(SurfViewer, self).__init__()
self.parent = parent
self.setFixedWidth(300)
self.setFixedHeight(100)
self.wid = QWidget()
self.setCentralWidget(self.wid)
# self.grid = QGridLayout()
self.globallayout = QVBoxLayout()
self.split_V = QSplitter(Qt.Vertical)
l_a = QLabel('A')
l_b = QLabel('B')
l_c = QLabel('C')
l_d = QLabel('D')
l_e = QLabel('E')
l_f = QLabel('F')
l_g = QLabel('G')
l_h = QLabel('H')
l_i = QLabel('I')
split_H = QSplitter(Qt.Horizontal)
split_H.addWidget(l_a)
split_H.addWidget(l_b)
split_H.addWidget(l_c)
self.split_V.addWidget(split_H)
split_H = QSplitter(Qt.Horizontal)
split_H.addWidget(l_d)
split_H.addWidget(l_e)
split_H.addWidget(l_f)
self.split_V.addWidget(split_H)
split_H = QSplitter(Qt.Horizontal)
split_H.addWidget(l_g)
split_H.addWidget(l_h)
split_H.addWidget(l_i)
self.split_V.addWidget(split_H)
self.globallayout.addWidget(self.split_V)
self.wid.setLayout(self.globallayout)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = SurfViewer(app)
ex.setWindowTitle('window')
ex.show()
sys.exit(app.exec_( ))
Update
I think I almost found a solution where a function is used so that whenever the vertical splits are changed, it re-aligns them:
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class SurfViewer(QMainWindow):
def __init__(self, parent=None):
super(SurfViewer, self).__init__()
self.parent = parent
self.setFixedWidth(300)
self.setFixedHeight(100)
self.wid = QWidget()
self.setCentralWidget(self.wid)
# self.grid = QGridLayout()
self.globallayout = QVBoxLayout()
self.split_V = QSplitter(Qt.Vertical)
l_a = QLabel('A')
l_b = QLabel('B')
l_c = QLabel('C')
l_d = QLabel('D')
l_e = QLabel('E')
l_f = QLabel('F')
l_g = QLabel('G')
l_h = QLabel('H')
l_i = QLabel('I')
self.split_H1 = QSplitter(Qt.Horizontal)
self.split_H1.addWidget(l_a)
self.split_H1.addWidget(l_b)
self.split_H1.addWidget(l_c)
self.split_V.addWidget(self.split_H1)
self.split_H2 = QSplitter(Qt.Horizontal)
self.split_H2.addWidget(l_d)
self.split_H2.addWidget(l_e)
self.split_H2.addWidget(l_f)
self.split_V.addWidget(self.split_H2)
self.split_H3 = QSplitter(Qt.Horizontal)
self.split_H3.addWidget(l_g)
self.split_H3.addWidget(l_h)
self.split_H3.addWidget(l_i)
self.split_V.addWidget(self.split_H3)
self.globallayout.addWidget(self.split_V)
self.wid.setLayout(self.globallayout)
self.split_H1.splitterMoved.connect(self.moveSplitter)
self.split_H2.splitterMoved.connect(self.moveSplitter)
self.split_H3.splitterMoved.connect(self.moveSplitter)
# self.split_H1.splitterMoved
# self.moveSplitter(0,self.split_H1.at )
def moveSplitter( self, index, pos ):
# splt = self._spltA if self.sender() == self._spltB else self._spltB
self.split_H1.blockSignals(True)
self.split_H2.blockSignals(True)
self.split_H3.blockSignals(True)
self.split_H1.moveSplitter(index, pos)
self.split_H2.moveSplitter(index, pos)
self.split_H3.moveSplitter(index, pos)
self.split_H1.blockSignals(False)
self.split_H2.blockSignals(False)
self.split_H3.blockSignals(False)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = SurfViewer(app)
ex.setWindowTitle('window')
ex.show()
sys.exit(app.exec_( ))
However, I still have an issue at the begining - the alignment is not correct :
I don't know How call the function moveSplitter in the __init__
It seems that directly calling moveSplitter (which is a protected method) may be problematic. Using Qt-5.10.1 with PyQt-5.10.1 on Linux, I found that it can often result in a core dump when called during __init__. There is probably a good reason why Qt provides setSizes as a public method for changing the position of the splitters, so it may be wise to prefer it over moveSplitter.
With that in mind, I arrived at the following implementation:
class SurfViewer(QMainWindow):
def __init__(self, parent=None):
...
self.split_H1.splitterMoved.connect(self.moveSplitter)
self.split_H2.splitterMoved.connect(self.moveSplitter)
self.split_H3.splitterMoved.connect(self.moveSplitter)
QTimer.singleShot(0, lambda: self.split_H1.splitterMoved.emit(0, 0))
def moveSplitter(self, index, pos):
sizes = self.sender().sizes()
for index in range(self.split_V.count()):
self.split_V.widget(index).setSizes(sizes)
The single-shot timer is needed because on some platforms the geometry of the window may not be fully initialized before it is shown on screen. And note that setSizes does not trigger splitterMoved, so there is no need to block signals when using it.
I created a QWizard object which contains several pages, I tried to open a file when NextButton of the specific page was clicked. At first, I triedQWizard.NextButton.clicked.connect(), came with :
"AttributeError: 'WizardButton' object has no attribute 'clicked''.
After that, I searched "WizardButton" in Qt Assistant, couldn't get any useful signals to emit, is it possible to implement that like QPushButton.clicked.connect()?
here's the specific page:
class AccountPage(QWizardPage):
def __init__(self, parent=None):
super(AccountPage, self).__init__(parent)
self.setTitle("Account Information")
NameLabel = QLabel("&Name:")
NameLineEdit = QLineEdit()
NameLabel.setBuddy(NameLineEdit)
EmailLabel = QLabel("&Email Address:")
EmailLineEdit = QLineEdit()
EmailLabel.setBuddy(EmailLineEdit)
PwdLabel = QLabel("&Password:")
PwdLineEdit = QLineEdit()
PwdLabel.setBuddy(PwdLineEdit)
self.registerField('Name*', NameLineEdit)
self.registerField('EmailAddress*', EmailLineEdit)
self.registerField('Password*', PwdLineEdit)
layout = QGridLayout()
layout.addWidget(NameLabel, 0, 0)
layout.addWidget(NameLineEdit, 0, 1)
layout.addWidget(EmailLabel, 1, 0)
layout.addWidget(EmailLineEdit, 1, 1)
layout.addWidget(PwdLabel, 2, 0)
layout.addWidget(PwdLineEdit, 2, 1)
self.setLayout(layout)
QWizard.NextButton.clicked.connect(self.setMB)
def setMB(self):
try:
with open('mb.ini', 'w') as actInfo:
actInfo.write('sj')
except IOError as err:
print('mb.ini error:' + str(err))
import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class Window(QWizard):
def __init__(self):
super(Window, self).__init__()
self.accoutPage = AccountPage()
self.secondPage = Page2()
self.thirdPage = Page3()
self.addPage(self.accoutPage)
self.addPage(self.secondPage)
self.addPage(self.thirdPage)
self.button(QWizard.NextButton).clicked.connect(self.accoutPage.setMB)
class AccountPage(QWizardPage):
def __init__(self, parent=None):
super(AccountPage, self).__init__(parent)
self.setTitle("Account Information")
self.NameLabel = QLabel("&Name:")
self.NameLineEdit = QLineEdit()
self.NameLabel.setBuddy(self.NameLineEdit)
self.EmailLabel = QLabel("&Email Address:")
self.EmailLineEdit = QLineEdit()
self.EmailLabel.setBuddy(self.EmailLineEdit)
self.PwdLabel = QLabel("&Password:")
self.PwdLineEdit = QLineEdit()
self.PwdLabel.setBuddy(self.PwdLineEdit)
self.registerField('Name*', self.NameLineEdit)
self.registerField('EmailAddress*', self.EmailLineEdit)
self.registerField('Password*', self.PwdLineEdit)
layout = QGridLayout()
layout.addWidget(self.NameLabel, 0, 0)
layout.addWidget(self.NameLineEdit, 0, 1)
layout.addWidget(self.EmailLabel, 1, 0)
layout.addWidget(self.EmailLineEdit, 1, 1)
layout.addWidget(self.PwdLabel, 2, 0)
layout.addWidget(self.PwdLineEdit, 2, 1)
self.setLayout(layout)
self.i = 0 #if you need to call it once
def setMB(self):
if self.i == 0:
print(self.PwdLineEdit.text(), self.i)
try:
with open('mb.ini', 'w') as actInfo:
actInfo.write('sj')
except IOError as err:
print('mb.ini error:' + str(err))
finally:
self.i += 1
class Page2(QWizardPage):
def __init__(self):
super(Page2, self).__init__()
class Page3(QWizardPage):
def __init__(self):
super(Page3, self).__init__()
def main():
app = QApplication(sys.argv)
app.setStyle('plastique')
window = Window()
window.setWizardStyle(1)
window.show()
app.exec_()
if __name__ == "__main__":
sys.exit(main())