Button1 is a png with no background but it displays with a gray background, I tried setting it to transparent but that just gave it a black background.
How can I make the button background transparent?
import wx
class windowClass(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, None, -1, 'test', size=(1000, 600))
display_size = wx.DisplaySize()
print display_size
path = "background.png"
bg = wx.Image(path, wx.BITMAP_TYPE_ANY)
bg = bg.Scale(display_size[0],display_size[1]).ConvertToBitmap()
self.back = wx.StaticBitmap(self, -1, bg, pos=(0,0))
path1 = wx.Image("button.png")
path1.Rescale(100, 100)
image1 = wx.BitmapFromImage(path1)
self.button1 = wx.StaticBitmap(self.back, -1, image1, (10, 10))
self.button1.Bind(wx.EVT_LEFT_DOWN, self.button1Click)
self.button1.SetBackgroundColour(wx.TransparentColour)
self.Show()
def button1Click(self,event):
self.Close()
def main():
app = wx.App()
windowClass(None)
app.MainLoop()
main()
Related
I am trying to make a choice game where you can write and rewrite a name of the character in the game but whenever I try to delete a letter whilst testing the code I get an Recursion error
What is the cause to this problem and how to avoid it?
Here is my code
import pygame as pg
pg.init()
import time
win = pg.display.set_mode((900,600))
pg.display.set_caption("Choices")
go = 0
user_text = ''
lbrown = 225, 156, 0
brown = 192, 128, 0
dbrown = 128, 64, 0
black = 0, 0, 0
dgrey = 64, 64, 64
grey = 128,128,128
lgrey = 192,192,192
white = 255, 255, 255
red = 255, 0, 0
orange = 255,128,0
yellow = 255,223,0
lgreen = 128,255,0
green = 0,255,0
dgreen = 0,128,0
turcoise = 0,192,128
lblue = 0,128,255
blue = 0,0,255
dblue = 0,0,128
blurple = 128,0,192
purple = 192,0,192
pirple = 167, 0, 167
rpink = 255,0,128
pink = 255,0,255
startclick = 0
class BG(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface([400,100])
self.image.fill(white)
self.rect = self.image.get_rect()
class START(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface([200,100])
self.image.fill(green)
self.rect = self.image.get_rect()
class START_TEXT(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
font = pg.font.SysFont('Comic Sans MS', 40)
self.image = font.render('Start',False, pink)
self.rect = self.image.get_rect()
bg = BG()
bg.rect.x = 25
bg.rect.y = 100
start = START()
start.rect.x = 450
start.rect.y = 260
start_txt = START_TEXT()
start_txt.rect.x = 495
start_txt.rect.y = 280
all_sprite = pg.sprite.Group()
all_sprite.add(start,start_txt)
win.fill(purple)
def redraw():
all_sprite.draw(win)
pg.display.update()
run = True
while run:
pos = pg.mouse.get_pos()
print(startclick)
for event in pg.event.get():
if event.type == pg.QUIT:
run = False
if start.rect.collidepoint(pos):
start.image.fill(dgreen)
if event.type == pg.MOUSEBUTTONDOWN:
startclick = 1
win.fill(black)
all_sprite.remove(start,start_txt)
else:
start.image.fill(green)
key = pg.key.get_pressed()
if key[pg.K_BACKSPACE]:
all_sprite.remove(bg, user_text)
user_text = user_text[:-1]
go = 1
else:
if event.type == pg.KEYDOWN:
user_text += event.unicode
usertex = user_text
class User_TxT(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
font = pg.font.SysFont('Comic Sans MS', 40)
self.image = font.render(usertex, True, pink)
self.rect = self.image.get_rect()
user_txt = User_TxT()
user_txt.rect.x = 70
user_txt.rect.y = 120
if startclick == 1:
all_sprite.add(bg, user_txt)
pg.display.flip()
redraw()
quit()
pg.quit()
And the Recursion Error
packages\pygame\sprite.py", line 471, in
if isinstance(sprite, Sprite):
RecursionError: maximum recursion depth exceeded while calling a Python object
Why is this happening?
I've modified your User_TxT sprite class to support an update function to change its text. This will prevent the need to remove and recreate the sprite which causes your recursion error.
import pygame as pg
pg.init()
import time
win = pg.display.set_mode((900,600))
pg.display.set_caption("Choices")
go = 0
user_text = ''
lbrown = 225, 156, 0
brown = 192, 128, 0
dbrown = 128, 64, 0
black = 0, 0, 0
dgrey = 64, 64, 64
grey = 128,128,128
lgrey = 192,192,192
white = 255, 255, 255
red = 255, 0, 0
orange = 255,128,0
yellow = 255,223,0
lgreen = 128,255,0
green = 0,255,0
dgreen = 0,128,0
turcoise = 0,192,128
lblue = 0,128,255
blue = 0,0,255
dblue = 0,0,128
blurple = 128,0,192
purple = 192,0,192
pirple = 167, 0, 167
rpink = 255,0,128
pink = 255,0,255
startclick = 0
class BG(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface([400,100])
self.image.fill(white)
self.rect = self.image.get_rect()
class START(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface([200,100])
self.image.fill(green)
self.rect = self.image.get_rect()
class START_TEXT(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
font = pg.font.SysFont('Comic Sans MS', 40)
self.image = font.render('Start',False, pink)
self.rect = self.image.get_rect()
class User_TxT(pg.sprite.Sprite):
def __init__(self, usertex):
pg.sprite.Sprite.__init__(self)
self.update(usertex)
def update(self, usertex):
font = pg.font.SysFont('Comic Sans MS', 40)
self.image = font.render(usertex, True, pink)
self.rect = self.image.get_rect()
bg = BG()
bg.rect.x = 25
bg.rect.y = 100
start = START()
start.rect.x = 450
start.rect.y = 260
start_txt = START_TEXT()
start_txt.rect.x = 495
start_txt.rect.y = 280
user_txt = User_TxT(user_text)
all_sprite = pg.sprite.Group()
all_sprite.add(start,start_txt)
win.fill(purple)
def redraw():
all_sprite.draw(win)
pg.display.update()
run = True
while run:
pos = pg.mouse.get_pos()
print(startclick)
for event in pg.event.get():
if event.type == pg.QUIT:
run = False
if start.rect.collidepoint(pos):
start.image.fill(dgreen)
if event.type == pg.MOUSEBUTTONDOWN:
startclick = 1
win.fill(black)
all_sprite.remove(start,start_txt)
else:
start.image.fill(green)
key = pg.key.get_pressed()
if key[pg.K_BACKSPACE]:
# all_sprite.remove(bg, user_text)
user_text = user_text[:-1]
go = 1
else:
if event.type == pg.KEYDOWN:
user_text += event.unicode
# usertex = user_text
user_txt.update(user_text)
user_txt.rect.x = 70
user_txt.rect.y = 120
if startclick == 1:
all_sprite.add(bg, user_txt)
startclick = 0
pg.display.flip()
redraw()
quit()
pg.quit()
I've tried to make minimal changes to your code to avoid confusion.
EDIT to add some additional explanation:
I changed the User_TxT sprite class to take an input string as its initial text string to display and to also have an update() function so that its text string can be changed. This function is also what we need to do when initialising the sprite, so to prevent duplication, it's called from __init__(). That way you only need to have one sprite. You were also redefining and instantiating the User_TxT class for every event, which is unnecessary.
To help identify the code differences, you can use a diff tool, like WinMerge on Windows, or the command line diff tool on Linux.
If you run into further issues with your code, you should ask a new question, if you create a Minimal, Reproducible Example it will make it easier to help you.
Please how can I add permanently different widgets in the tabs and save them permanently
<html>
<pre>
import wx
tabs = []
with open('test.txt','r') as file:
for element in file.readlines():
tabs.append(element)
class TabPanel(wx.Panel):
def __init__(self, parent, pageNum):
self.parent = parent
self.pageNum = pageNum
wx.Panel.__init__(self, parent=parent)
class DemoFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Notebook", size=(600,400))
panel = wx.Panel(self)
self.tab_num = len(tabs)
self.notebook = wx.Notebook(panel)
for tab in tabs:
name = "Page " + str(tab)
tab = TabPanel(self.notebook, 1)
self.notebook.AddPage(tab, name)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.notebook, 1, wx.ALL|wx.EXPAND, 5)
btn = wx.Button(panel, label="Add Page")
btn.Bind(wx.EVT_BUTTON, self.addPage)
sizer.Add(btn)
panel.SetSizer(sizer)
self.Layout()
self.Show()
def addPage(self, event):
self.tab_num += 1
new_tab = TabPanel(self.notebook, self.tab_num)
self.notebook.AddPage(new_tab, "Page %s" % self.tab_num)
tabs.append(self.tab_num)
print()
with open('test.txt','a+') as file:
file.write(str(self.tab_num))
file.write('\n')
if __name__ == "__main__":
app = wx.App(False)
frame = DemoFrame()
app.MainLoop()
</pre>
</html>
Something like this should get you started (sorry not readdly familiar with python):
class DemoFrame(wx.Frame):
def __init__(self):
self.tab_num = 1
wx.Frame.__init__(self, None, wx.ID_ANY, "Notebook", size=(600,400))
panel = wx.Panel(self)
with open( "test.txt", "r" as file:
self.tab_num = file.read()
self.notebook = wx.Notebook(panel)
for tab in [1..self.tab_num]:
name = "Page " + str(tab)
tab = TabPanel(self.notebook, 1)
self.notebook.AddPage(tab, name)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.notebook, 1, wx.ALL|wx.EXPAND, 5)
btn = wx.Button(panel, label="Add Page")
btn.Bind(wx.EVT_BUTTON, self.addPage)
sizer.Add(btn)
panel.SetSizer(sizer)
self.Layout()
self.Show()
def addPage(self, event):
self.tab_num += 1
new_tab = TabPanel(self.notebook, self.tab_num)
self.notebook.AddPage(new_tab, "Page %s" % self.tab_num)
tabs.append(self.tab_num)
print()
with open('test.txt','a+') as file:
file.write(str(self.tab_num))
file.write('\n')
if __name__ == "__main__":
app = wx.App(False)
frame = DemoFrame()
app.MainLoop()
from PyQt5.QtWidgets import QGraphicsItem
from PyQt5.QtSvg import QGraphicsSvgItem, QSvgRenderer
from PyQt5.QtCore import Qt, QRectF
class MyItem(QGraphicsItem):
def __init__(self, parent ):
super().__init__( parent = parent )
self.textRect = QRectF( 0,0,100,100 )
self.SvgGItem = QGraphicsSvgItem(self)
self.Svg_renderer = QSvgRenderer("./item.svg")
self.SvgGItem.setSharedRenderer ( self.Svg_renderer )
self.SvgGItem.setElementId( "1" )
def paint(self, painter, option, widget):
alignFlags = Qt.AlignLeft | Qt.AlignTop
painter.drawText( self.textRect, alignFlags , "text" )
I want the text being above the svg item. This code is for example, the real code is pretty difficult, but the sence is the same. setZValue() does not work in this case and it is clear. There is some way or other decision?
Try it:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtSvg import QGraphicsSvgItem, QSvgRenderer
class MyItem(QGraphicsItem):
def __init__(self):
super().__init__()
self.x = 0
self.y = 0
self.w = 100
self.h = 100
self.width = 8
self.text = "None"
self.setFlags(MyItem.ItemIsSelectable | MyItem.ItemIsMovable)
def boundingRect(self):
return QRectF(self.x, self.y, self.w, self.h)
def paint(self, painter, option, widget):
painter.setPen(QPen(Qt.blue, self.width))
rec = self.boundingRect().adjusted(self.width / 2,
self.width / 2,
-self.width / 2,
-self.width / 2)
painter.setBrush(Qt.yellow)
painter.drawRect(rec)
painter.setFont(QFont("Arial", 16))
self.textRect = QRectF( 0, 0, 100, 100 )
alignFlags = Qt.AlignCenter
painter.drawText( self.textRect, alignFlags , "! text !" )
class MySvg(QGraphicsSvgItem):
def __init__(self):
super(MySvg, self).__init__('blank.svg')
self.setFlags(QGraphicsItem.ItemIsSelectable|
QGraphicsItem.ItemIsMovable)
class GraphicsScene(QGraphicsScene):
def __init__(self):
super().__init__()
self.setSceneRect(-200, -200, 400, 400)
self.fillScene()
def fillScene(self):
test = MySvg()
self.addItem(test)
item = MyItem()
self.addItem(item)
def drawBackground(self, painter, rect):
painter.setPen(QPen(Qt.green, 3))
painter.drawRect(self.sceneRect())
painter.setPen(QPen(Qt.red, 3))
painter.drawText(0, 0, '0')
painter.drawText(-200, -200, '-200')
painter.drawText(200, 200, '200')
class Main(QWidget):
def __init__(self):
super(Main, self).__init__()
self.scene = GraphicsScene()
self.view = QGraphicsView(self)
self.view.setScene(self.scene)
hbox = QHBoxLayout()
hbox.addWidget(self.view)
self.setLayout(hbox)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Main()
ex.show()
sys.exit(app.exec_())
I am trying to create a custom widget and adding it to a listwidget following the example here but used a widget as here(Answer) instead of the progress bar. The custom widget works fine independently. But when it is added to the list widget, the horizontal scrolling works perfect but the vertical scroll covers only a portion of the image. Can somebody suggest some improvement?
The code is
import sys
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class MainWidget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.scene = QtGui.QGraphicsScene()
self.view = QtGui.QGraphicsView(self.scene)
layout = QtGui.QVBoxLayout()
layout.addWidget(self.view)
self.setLayout(layout)
self.pixmap_item = QtGui.QGraphicsPixmapItem(QtGui.QPixmap('image.png'), None, self.scene)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(800, 600)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.listWidget = QtGui.QListWidget(self.centralwidget)
self.listWidget.setGeometry(QtCore.QRect(170, 20, 400, 400))
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth())
self.listWidget.setSizePolicy(sizePolicy)
self.listWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
self.listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
self.listWidget.setObjectName(_fromUtf8("listWidget"))
self.pushButton = QtGui.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(40, 200, 113, 32))
self.pushButton.setObjectName(_fromUtf8("pushButton"))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.pushButton.setText(_translate("MainWindow", "PushButton", None))
class MyForm(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.pushButton.clicked.connect(self.progress)
def progress(self):
item = QtGui.QListWidgetItem(self.ui.listWidget)
item_widget = MainWidget()
item.setSizeHint(item_widget.sizeHint())
self.ui.listWidget.addItem(item)
self.ui.listWidget.setItemWidget(item,item_widget)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
and here is the test image:
I want to rotate a QLabel so that it is oriented vertically. A similar question was asked here: PyQT: Rotate a QLabel so that it's positioned diagonally instead of horizontally but the code in answer causes a recursive loop issue.
Here is the code I am using, why does the code run in a recursive loop and why are the labels not drawn?:
from PyQt4.QtGui import QLabel, QPainter
from PyQt4.QtCore import QSize
from PyQt4 import QtCore, QtGui
import sys
class VerticalLabel(QLabel):
def __init__(self, text = ""):
QtGui.QLabel.__init__(self, text)
self.text = text
def paintEvent(self, event):
painter = QPainter(self)
painter.setPen(QtCore.Qt.black)
painter.translate(0, self.height()-1)
painter.rotate(-90)
self.setGeometry(self.x(), self.y(), self.height(), self.width())
painter.drawText(0, 0, self.text)
print("text: {0}".format(self.text))
painter.end()
def minimumSizeHint(self):
size = QLabel.minimumSizeHint(self)
return QSize(size.height(), size.width())
def sizeHint(self):
size = QLabel.sizeHint(self)
return QSize(size.height(), size.width())
def setText(self, newText):
self.text = newText
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
lbl1 = VerticalLabel('label 1')
lbl2 = VerticalLabel('label 2')
lbl3 = VerticalLabel('label 3')
hBoxLayout = QtGui.QHBoxLayout()
hBoxLayout.addWidget(lbl1)
hBoxLayout.addWidget(lbl2)
hBoxLayout.addWidget(lbl3)
self.setLayout(hBoxLayout)
self.setGeometry(300, 300, 250, 150)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
This is slightly modified version of the same code from another answer and remember if you put any print under paintEvent it will print every time if you have any activity on the widget like mouse move or re size or what ever even a touch in window will redraw, because that's what paintEvent means.
class MyLabel(QtGui.QWidget):
def __init__(self, text=None):
super(self.__class__, self).__init__()
self.text = text
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setPen(QtCore.Qt.black)
painter.translate(20, 100)
painter.rotate(-90)
if self.text:
painter.drawText(0, 0, self.text)
painter.end()
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
lbl1 = MyLabel('lbl 1')
lbl2 = MyLabel('lbl 2')
lbl3 = MyLabel('lbl 3')
hBoxLayout = QtGui.QHBoxLayout()
hBoxLayout.addWidget(lbl1)
hBoxLayout.addWidget(lbl2)
hBoxLayout.addWidget(lbl3)
self.setLayout(hBoxLayout)
self.setGeometry(300, 300, 250, 150)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()