Here is my code:
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class Editor(QPlainTextEdit):
def __init__(self, parent):
super(Editor, self).__init__()
self.setPlainText( u'apple, banana\norange\nblah blah\n\nOh yeah!....\n'*2 )
self.setParent( parent )
self.setWordWrapMode( QTextOption.NoWrap )
self.setViewportMargins( 50,0,0,0 )
QObject.connect( self, SIGNAL("textChanged()"), self.repainting )
def repainting(self) : self.parent().update()
class WinE(QMainWindow):
def __init__(self, font=QFont( 'Monospace', 12 )):
super(WinE, self).__init__()
self.font = font
self.font.setFixedPitch( True )
self.ce = Editor( self )
self.ce.setFont( self.font )
self.setWindowTitle('Code Editor')
self.textr = QRect( 3, 5, self.ce.childrenRect().x() -12, self.ce.childrenRect().height() )
self.setGeometry( QRect(800, 840, 351, 250) )
self.setCentralWidget( self.ce )
self.show()
def paintEvent(self, event):
qp = QPainter ()
qp.begin ( self )
self.drawLiNums ( qp )
qp.end ()
def drawLiNums(self, qp):
qp.setPen ( QColor(255, 255, 255) )
qp.setFont ( self.font )
qp.drawText ( self.textr, Qt.AlignRight, self.lineNumeration() )
def lineNumeration(self):
return ''.join( [str(n+1) +'\n' for n in range( len(self.ce.toPlainText().splitlines(False)) )] )
def main():
app = QApplication(sys.argv)
ex = WinE()
sys.exit(app.exec_())
if __name__ == '__main__': main()
Editor shows up with numbers, and the numbers are updating when adding new lines. But when it reaches the end of the widget, the text continues to scroll while typing, but the line numbers stop updating, and there's no scrolling whatsoever on line number area!
I hope this solves your problem!
I simply called parent().update() every time the text is scrolled down. And I started the lineNumeration at the first visible line (line=block in qt)
Best wishes, MrP :)
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class Editor(QPlainTextEdit):
def __init__(self, parent):
super(Editor, self).__init__()
self.setPlainText( u'apple, banana\norange\nblah blah\n\nOh yeah!....\n'*6 )
self.setParent( parent )
self.setWordWrapMode( QTextOption.NoWrap )
self.setViewportMargins( 50,0,0,0 )
QObject.connect( self, SIGNAL("textChanged()"), self.repainting )
def repainting(self):
self.parent().update()
def scrollContentsBy(self, *args, **kwargs):
self.parent().update()
return QPlainTextEdit.scrollContentsBy(self, *args, **kwargs)
class WinE(QMainWindow):
def __init__(self, font=QFont( 'Monospace', 12 )):
super(WinE, self).__init__()
self.font = font
self.font.setFixedPitch( True )
self.ce = Editor( self )
self.ce.setFont( self.font )
self.setWindowTitle('Code Editor')
self.textr = QRect( 3, 5, self.ce.childrenRect().x() -12, self.ce.childrenRect().height() )
self.setGeometry( QRect(800, 840, 351, 250) )
self.setCentralWidget( self.ce )
self.show()
def paintEvent(self, event):
qp = QPainter ()
qp.begin ( self )
self.drawLiNums ( qp )
qp.end ()
def drawLiNums(self, qp):
qp.setPen ( QColor(255, 255, 255) )
qp.setFont ( self.font )
qp.drawText ( self.textr, Qt.AlignRight, self.lineNumeration() )
def lineNumeration(self):
offset=self.ce.firstVisibleBlock().firstLineNumber()
return ''.join(str(i)+"\n" for i in range(offset+1, self.ce.blockCount()+1))
def main():
app = QApplication(sys.argv)
ex = WinE()
sys.exit(app.exec_())
if __name__ == '__main__': main()
Related
I have created a gui in PyQt5, and have several window-classes controlled by a class called Controller.
Background:
In one of the window(A) you can push buttons and a new window(B) pops up and A is disabled. Then when quit button is pressed from window B it goes back to window A without saving edits in window B and enables window A, and if continue button is pressed in B, then it reopens window A and enables it.
Problem:
However, when the x button in the corner of window B is pressed the window is closed and window A is disabled. My question is therefore: How can I make window A enable again when B is closed?
Can I override the red corner x event such that I can be able to enable window A again?
PS! I tried to make the code minimal and reproducible, let me know if there is something I should fix:)
import sys
from PyQt5 import QtCore, QtWidgets
class WindowTwo(QtWidgets.QWidget):
switch_window = QtCore.pyqtSignal()
def __init__(self, M, S):
QtWidgets.QWidget.__init__(self)
self.S = S
self.M = M
self.setupUi ( self )
self.setWindowTitle ( 'M' )
def setupUi(self, CM):
CM.setEnabled ( True )
CM.setFocusPolicy ( QtCore.Qt.TabFocus )
layout = QtWidgets.QGridLayout()
layout.addWidget(QtWidgets.QLabel("M: " ),0,0)
layout.addWidget(QtWidgets.QLabel("S: " ),0,1)
self.QuitButton = QtWidgets.QPushButton ( "Quit" )
self.QContinueButton = QtWidgets.QPushButton ( "Continue" )
self.QuitButton.clicked.connect ( CM.close )
self.QContinueButton.clicked.connect( lambda: self.windowtwo(self.M))
layout.addWidget( self.QuitButton, 10, 1 )
layout.addWidget ( self.QContinueButton, 10, 2 )
self.setLayout ( layout )
def windowtwo( self, M):
self.M = M
self.switch_window.emit()
class MS(QtWidgets.QWidget):
switch_window = QtCore.pyqtSignal(int)
def __init__(self, M, S):
QtWidgets.QWidget.__init__(self)
self.S = S
self.M = M
self.setupUi ( self )
self.setWindowTitle ( 'M' )
def setupUi(self, CM):
CM.setEnabled ( True )
CM.setFocusPolicy ( QtCore.Qt.TabFocus )
layout = QtWidgets.QGridLayout()
layout.addWidget(QtWidgets.QLabel("M: " ),0,0)
layout.addWidget(QtWidgets.QLabel("S: " ),0,1)
self.QWindowTwoButton = QtWidgets.QPushButton ( ' Go to other window')
self.QuitButton = QtWidgets.QPushButton ( "Quit" )
self.QContinueButton = QtWidgets.QPushButton ( "Continue" )
self.QuitButton.clicked.connect ( CM.close )
self.QWindowTwoButton.clicked.connect( lambda b=0, a= 400 : self.windowms(a))
layout.addWidget( self.QuitButton, 10, 1 )
layout.addWidget ( self.QContinueButton, 10, 2 )
layout.addWidget ( self.QWindowTwoButton, 10, 3 )
self.setLayout ( layout )
def windowms( self, a):
a = 100
self.switch_window.emit(a)
class Controller:
def __init__(self):
self.M = 5
self.S = 7
self.A = 8
# pass
def show_window_two(self):
self.window_two = WindowTwo(self.M, self.S)
self.window_two.switch_window.connect(self.show_window_three)
self.window_two.show()
def show_window_three(self):
try:
self.A = self.window_four.A
except:
pass
self.window_three = MS(self.M, self.S)
self.mscrollArea = QtWidgets.QScrollArea()
self.mscrollArea.setWidget(self.window_three)
self.mscrollArea.setDisabled(0)
self.window_three.switch_window.connect(self.show_window_four)
self.window_three.QuitButton.clicked.connect(self.mscrollArea.close)
self.mscrollArea.show()
self.mscrollArea.resize(700, 500)
self.mscrollArea.setWindowTitle("MS")
self.window_two.close()
try:
self.window_four.close()
except:
pass
def show_window_four(self, a):
if (a == 100):
self.window_four = WindowTwo(self.M, self.S)
self.window_four.switch_window.connect(self.show_window_three)
self.mscrollArea.setDisabled(1)
self.window_four.QuitButton.clicked.connect(lambda: self.window_four.close)
self.window_four.QuitButton.clicked.connect(lambda: self.mscrollArea.setDisabled(0))
self.window_four.show()
#Here is an else if a is other values to open other windows
def main():
app = QtWidgets.QApplication(sys.argv)
controller = Controller()
controller.show_window_two()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The closeEvent is fired whenever a widget is closed, for example by clicking the "X" in the corner. Just override it with your own code to show the main window again, or emit a signal to inform your Controller.
from PyQt5 import QtWidgets
app = QtWidgets.QApplication.instance() or QtWidgets.QApplication([])
class W1(QtWidgets.QWidget):
def closeEvent(self, event):
print("closing w1")
class W2(QtWidgets.QWidget):
def __init__(self, w1):
super().__init__()
self.w1 = w1
def closeEvent(self, event):
print("closing w2")
self.w1.show()
w1 = W1()
w2 = W2(w1)
w2.show()
app.exec_()
I'm trying to redo this Qt code https://github.com/laserpants/qt-material-widgets but using Python & PyQt4 and I'm encountering problem with animation.
I want to recreate the checkbox of the example, everything is working fine except the animation; it doesn't update.
The main issue is that I want to keep the stateMachine and the transitions for the button, but the solutions I found does not use them.
I just want the icon to fade-in & out when clicked
any Idea why this is not working?
class materialCheckBox(QWidget):
clicked = pyqtSignal()
def __init__(self, parent):
super(materialCheckBox,self).__init__(parent)
self.setProperty("value", bool)
checkedIcon = materialIcon(self, "C:/Users/User/.qgis2/python/plugins/Material/icons/baseline-check_box-24px.svg")
uncheckedIcon = materialIcon(self, "C:/Users/User/.qgis2/python/plugins/Material/icons/baseline-check_box_outline_blank-24px.svg")
self.stateMachine = QStateMachine()
self.checkedState = QState()
self.checkedState.assignProperty(self, "value", True)
self.checkedState.assignProperty(checkedIcon, "opacity", 1.0)
self.checkedState.assignProperty(uncheckedIcon, "opacity", 0.0)
self.uncheckedState = QState()
self.uncheckedState.assignProperty(self, "value", False)
self.uncheckedState.assignProperty(checkedIcon, "opacity", 0.0)
self.uncheckedState.assignProperty(uncheckedIcon, "opacity", 1.0)
self.stateMachine.addState(self.checkedState)
self.stateMachine.addState(self.uncheckedState)
self.stateMachine.setInitialState(self.uncheckedState)
transition1 = self.checkedState.addTransition(self.clicked, self.uncheckedState)
animation1 = QPropertyAnimation(checkedIcon, "opacity", self)
animation1.setDuration(2000)
transition1.addAnimation(animation1)
animation2 = QPropertyAnimation(uncheckedIcon, "opacity", self)
animation2.setDuration(2000)
transition1.addAnimation(animation2)
transition2 = self.uncheckedState.addTransition(self.clicked, self.checkedState)
animation3 = QPropertyAnimation(checkedIcon, "opacity", self)
animation3.setDuration(2000)
transition2.addAnimation(animation3)
animation4 = QPropertyAnimation(uncheckedIcon, "opacity", self)
animation4.setDuration(2000)
transition2.addAnimation(animation4)
self.stateMachine.start()
self.clicked.connect(self.update)
self.setGeometry(0, 0, 24, 24)
def isChecked(self):
return self.property("value")
def mousePressEvent(self, event):
self.clicked.emit()
class materialIcon(QWidget):
def __init__(self, parent, address):
super(materialIcon, self).__init__(parent)
self.icon = QPixmap(address)
self.setProperty("opacity", float)
def paintEvent(self, event):
painter = QPainter(self)
painter.begin(self)
painter.setOpacity(self.property("opacity"))
mask = QPainter(self.icon)
mask.begin(self.icon)
mask.setCompositionMode(QPainter.CompositionMode_SourceIn)
mask.fillRect(self.icon.rect(), QColor(0, 158, 227))
mask.end()
painter.drawPixmap(0, 0, self.icon)
painter.end()
You have to call the update() method every time the opacity changes, so it's better to create a pyqtProperty than a dynamic property:
import os
from PyQt4 import QtCore, QtGui
root_path = os.path.dirname(os.path.realpath(__file__))
icons_path = file = os.path.join(root_path, "icons")
class MaterialCheckBox(QtGui.QWidget):
clicked = QtCore.pyqtSignal()
toggled = QtCore.pyqtSignal(bool)
def __init__(self, parent=None):
super(MaterialCheckBox, self).__init__(parent)
self._is_checked = False
checkedIcon = MaterialIcon(
self, os.path.join(icons_path, "baseline-check_box-24px.svg")
)
uncheckedIcon = MaterialIcon(
self,
os.path.join(
icons_path, "baseline-check_box_outline_blank-24px.svg"
),
)
stateMachine = QtCore.QStateMachine(self)
checkedState = QtCore.QState()
checkedState.assignProperty(self, b"checked", True)
checkedState.assignProperty(checkedIcon, b"opacity", 1.0)
checkedState.assignProperty(uncheckedIcon, b"opacity", 0.0)
uncheckedState = QtCore.QState()
uncheckedState.assignProperty(self, b"checked", False)
uncheckedState.assignProperty(checkedIcon, b"opacity", 0.0)
uncheckedState.assignProperty(uncheckedIcon, b"opacity", 1.0)
stateMachine.addState(checkedState)
stateMachine.addState(uncheckedState)
stateMachine.setInitialState(uncheckedState)
duration = 2000
transition1 = checkedState.addTransition(self.clicked, uncheckedState)
animation1 = QtCore.QPropertyAnimation(
checkedIcon, b"opacity", self, duration=duration
)
transition1.addAnimation(animation1)
animation2 = QtCore.QPropertyAnimation(
uncheckedIcon, b"opacity", self, duration=duration
)
transition1.addAnimation(animation2)
transition2 = uncheckedState.addTransition(self.clicked, checkedState)
animation3 = QtCore.QPropertyAnimation(
checkedIcon, b"opacity", self, duration=duration
)
transition2.addAnimation(animation3)
animation4 = QtCore.QPropertyAnimation(
uncheckedIcon, b"opacity", self, duration=duration
)
transition2.addAnimation(animation4)
stateMachine.start()
def sizeHint(self):
return QtCore.QSize(24, 24)
def isChecked(self):
return self._is_checked
def setChecked(self, value):
if self._is_checked != value:
self._is_checked = value
self.toggled.emit(self._is_checked)
checked = QtCore.pyqtProperty(
bool, fget=isChecked, fset=setChecked, notify=toggled
)
def mousePressEvent(self, event):
self.clicked.emit()
self.update()
super(MaterialCheckBox, self).mousePressEvent(event)
class MaterialIcon(QtGui.QWidget):
opacityChanged = QtCore.pyqtSignal()
def __init__(self, parent, address):
super(MaterialIcon, self).__init__(parent)
self.icon = QtGui.QPixmap(address)
self._opacity = 0.0
def opacity(self):
return self._opacity
def setOpacity(self, o):
if o != self._opacity:
self._opacity = o
self.opacityChanged.emit()
self.update()
opacity = QtCore.pyqtProperty(
float, fget=opacity, fset=setOpacity, notify=opacityChanged
)
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setOpacity(self.opacity)
mask = QtGui.QPainter(self.icon)
mask.setCompositionMode(QtGui.QPainter.CompositionMode_SourceIn)
mask.fillRect(self.icon.rect(), QtGui.QColor(0, 158, 227))
mask.end()
painter.drawPixmap(0, 0, self.icon)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = MaterialCheckBox()
w.show()
sys.exit(app.exec_())
The complete example is here.
I need to make a Panel scrollable. I've used GridBagSizer
Code:
import wx
class MyFrame( wx.Frame ):
def __init__( self, parent, ID, title ):
wx.Frame.__init__( self, parent, ID, title, wx.DefaultPosition, wx.Size( 400, 300 ) )
self.InitUI()
self.Center()
self.Show()
def InitUI(self):
MPanel = wx.Panel(self)
GridBag = wx.GridBagSizer(2, 2)
CO = ["RED", "BLUE"]
for i in range(10):
X = wx.StaticText(MPanel, size=(50,50), style=wx.ALIGN_CENTER, label="")
X.SetBackgroundColour(CO[i%2])
GridBag.Add(X, pos=(i+1, 1), flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=1)
GridBag.AddGrowableCol(1)
MPanel.SetSizerAndFit(GridBag)
class MyApp( wx.App ):
def OnInit( self ):
self.fr = MyFrame( None, -1, "K" )
self.fr.Show( True )
self.SetTopWindow( self.fr )
return True
app = MyApp( 0 )
app.MainLoop()
How can I do this?
Try if following solution helps you:
import wx
import wx.lib.scrolledpanel as scrolled
class MyPanel(scrolled.ScrolledPanel):
def __init__(self, parent):
scrolled.ScrolledPanel.__init__(self, parent, -1)
self.SetAutoLayout(1)
self.SetupScrolling()
Now Instead of using MPanel=wx.Panel(self), use `MPanel = MyPanel(self) and rest of your code will remain as is.
Below is the modified code:
class MyFrame( wx.Frame ):
def __init__( self, parent, ID, title ):
wx.Frame.__init__( self, parent, ID, title, wx.DefaultPosition, wx.Size( 400, 300 ) )
self.InitUI()
self.Center()
self.Show()
def InitUI(self):
MPanel = MyPanel(self)
GridBag = wx.GridBagSizer(2, 2)
CO = ["RED", "BLUE"]
for i in range(10):
X = wx.StaticText(MPanel, size=(50,50), style=wx.ALIGN_CENTER, label="")
X.SetBackgroundColour(CO[i%2])
GridBag.Add(X, pos=(i+1, 1), flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=1)
GridBag.AddGrowableCol(1)
MPanel.SetSizerAndFit(GridBag)
class MyApp( wx.App ):
def OnInit( self ):
self.fr = MyFrame( None, -1, "K" )
self.fr.Show( True )
self.SetTopWindow( self.fr )
return True
app = MyApp( 0 )
app.MainLoop()
I need to be able to send text from class "node" in node.py:
import datetime
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class node( QGraphicsItem ):
def __init__( self, position, scene ):
super( node, self ).__init__( None, scene )
self.setFlags( QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable )
self.rect = QRectF( -30, -30, 120, 60 )
self.setPos( position )
scene.clearSelection()
def sendFromNodeToBox( self, text ):
# how do i send text from here to textBox?
pass
def boundingRect( self ):
return self.rect
def paint( self, painter, option, widget ):
painter.setRenderHint( QPainter.Antialiasing )
pen = QPen( Qt.SolidLine )
pen.setColor( Qt.black )
pen.setWidth( 3 )
if option.state & QStyle.State_Selected:
#####################
self.sendFromNodeToBox( 'node selected' )
#####################
self.setZValue( 1 )
pen.setWidth( 4 )
pen.setColor( Qt.green )
else:
pen.setWidth( 3 )
self.setZValue( 0 )
painter.setPen( pen )
painter.setBrush( QColor( 200, 0, 0 ) )
painter.drawRoundedRect( self.rect, 10.0, 10.0 )
to statusBox in mainWindow.ui, which is being loaded by mainWindow.py
import os, sip, sys, subprocess, platform
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.uic import *
from PyQt4.QtOpenGL import *
from src.node import *
app = None
class mainWindow( QMainWindow ):
def __init__( self, parent = None ):
super( mainWindow, self ).__init__( parent )
self.currentPlatform = platform.system()
if self.currentPlatform == "Windows":
self.ui = loadUi( r'ui\mainWindow.ui', self )
elif self.currentPlatform == "Darwin":
self.ui = loadUi( r'ui/mainWindow.ui', self )
else:
print 'platform not supported'
quit()
# Scene view
self.scene = SceneView()
self.nodeDropGraphicsView.setViewport( QGLWidget( QGLFormat( QGL.SampleBuffers ) ) )
self.nodeDropGraphicsView.setScene( self.scene )
self.sendTextToBox( 'this text comes from mainWindow class, line 37 and 38.\n' )
self.sendTextToBox( 'press right mouse button.\n' )
def sendTextToBox( self, text ):
cursorBox = self.statusBox.textCursor()
cursorBox.movePosition(cursorBox.End)
cursorBox.insertText( str( text ) )
self.statusBox.ensureCursorVisible()
class SceneView( QGraphicsScene ):
def __init__( self, parent=None ):
super( SceneView, self ).__init__( parent )
text = self.addText( 'title' )
def mousePressEvent( self, event ):
pos = event.scenePos()
if event.button() == Qt.MidButton:
pass
elif event.button() == Qt.RightButton:
newNode = node( pos, self )
super( SceneView, self ).mousePressEvent( event )
def mouseReleaseEvent( self, event ):
print 'mouseReleaseEvent'
self.line = None
super( SceneView, self ).mouseReleaseEvent( event )
if __name__ == "__main__":
app = QApplication( sys.argv )
screenSize = QApplication.desktop().availableGeometry()
window = mainWindow()
window.resize( int( screenSize.width() ), int( screenSize.height() ) )
window.show()
app.exec_()
App runs on win and osx. Linux not tested yet.
Python 2.7 and Qt 4.8 required.
Any suggestions?
The full source is here:
https://www.dropbox.com/sh/lcetrurnemr2cla/AAD-Z6ijgTrG0qVU_cum5viua?dl=0
Help is being much appreciated.
One way to do this would be to define a custom signal on the SceneView class, and then the graphics item can emit the text via its scene:
class node( QGraphicsItem ):
...
def sendFromNodeToBox( self, text ):
self.scene().textMessage.emit(text)
class SceneView( QGraphicsScene ):
textMessage = pyqtSignal(str)
class mainWindow( QMainWindow ):
def __init__( self, parent = None ):
...
self.scene = SceneView()
self.scene.textMessage.connect(self.sendTextToBox)
I just started to lear the PyQt, but I got some problem. Here is my code:
class GUI( QtGui.QMainWindow ):
'''
classdocs
'''
"""**********************************************************************"""
""" Constructor """
"""**********************************************************************"""
def __init__( self, parent = None ):
self.app = QtGui.QApplication( sys.argv )
QtGui.QMainWindow.__init__( self )
"""******************************************************************"""
""" Settintg up the windows """
"""******************************************************************"""
self.resize( 1024, 756 )
self.setWindowTitle( 'Windscanner - Core Module' )
self.setWindowIcon( QtGui.QIcon( 'icons/Windsock.png' ) )
""" Text Area """
self.messageField = QtGui.QTextEdit() # Alternative: QTextEdit
self.messageField.setReadOnly( True )
""" Input """
self.inputLine = QtGui.QLineEdit()
""" Send Button """
sendButton = QtGui.QPushButton( 'TCP: Send' )
sendButton.setStatusTip( 'Send manually inserted message via TCP' )
sendButton.setToolTip( 'Send manually inserted message via TCP' )
self.connect( sendButton, QtCore.SIGNAL( 'clicked()' ), self.f_sendbutton )
sendButton.setGeometry( 300, 300, 250, 150 );
""" Layout """
mainLayout = QtGui.QGridLayout()
mainLayout.addWidget( self.messageField )
mainLayout.addWidget( self.inputLine )
mainLayout.addWidget( sendButton )
""" Widget """
mainWidget = QtGui.QWidget()
mainWidget.setLayout( mainLayout )
self.setCentralWidget( mainWidget )
self.show()
sys.exit( self.app.exec_() )
My question is how can I define the size and geometry of the textarea and the button?
I tryed to use the
setGeometry()
but it not really working.
You can use:
sendButton.setMinimumSize()
and
mainLayout.setRowMinimumHeight()