how to switch widgets in a QSplitter - pyqt

How to modify a QSplitter panels from right to left, or center, without deleting the splitter and recreate it.
I uses replaceWidget, but it is giving: QSplitter::replaceWidget: Trying to replace a widget with one of its siblings, and QSplitter::replaceWidget: Trying to replace a widget with itself
widget_1, widget_2, widget_3, widget_4 = QWidget(), QWidget(), QWidget(), QWidget()
splitter1 = QSplitter(Qt.Vertical)
splitter1.addWidget(widget_1)
splitter1.addWidget(widget_2)
splitter1.setSizes([450, 350])
splitter2 = QSplitter(Qt.Vertical)
splitter2.addWidget(widget_3)
splitter2.addWidget(widget_4)
splitter2.setSizes([550, 250])
splitter3 = QSplitter(Qt.Horizontal)
splitter3.setObjectName('align_left')
splitter3.addWidget(splitter1)
splitter3.addWidget(splitter2)
splitter3.setSizes([100, 1000])
right_panel, left_panel = splitter3.widget(0), splitter3.widget(1)
splitter3.replaceWidget(0, left_panel)
splitter3.replaceWidget(1, right_panel)
I further tried to create two QSplitter using the same instances, but seems i need to create different instances for each QSplitter
I tried also, but not working
for i in reversed(range(splitter3.count())):
panel = splitter3.widget(i)
panel.setParent(None)
if align_panel == 'left':
splitter3.addWidget(splitter1)
splitter3.addWidget(splitter2)
splitter3.setSizes([100, 1000])
elif align_panel == 'right':
splitter3.addWidget(splitter2)
splitter3.addWidget(splitter1)
splitter3.setSizes([1000, 100])

Related

Qt3D Window and two layers, viewports, layerfilters, etc

I want to code a Qt3DWindow where I would have two QLayer-s, QLayerFilter-s, QViewport-s, etc. I need this because I want to render entities in QViewport 1 in a usual way and entities in QViewport 2 always visible (even when they are actually behind entities 1).
Here is my code:
class Window(Qt3DExtras.Qt3DWindow):
def __init__(self):
super().__init__()
self.root_entity = Qt3DCore.QEntity()
self.entity_1 = Qt3DCore.QEntity(self.root_entity)
self.entity_2 = Qt3DCore.QEntity(self.root_entity)
self.setRootEntity(self.root_entity)
# some other code
self.surselector = Qt3DRender.QRenderSurfaceSelector()
self.surselector.setSurface(self)
# Viewport 1
self.viewport_1 = Qt3DRender.QViewport(self.surselector)
self.layerfilter_1 = Qt3DRender.QLayerFilter(self.viewport_1)
self.layer_1 = Qt3DRender.QLayer(self.entity_1)
self.entity_1.addComponent(self.layer_1)
self.layer_1.setRecursive(True)
self.layerfilter_1.addLayer(self.layer_1)
self.cameraSelector_1 = Qt3DRender.QCameraSelector(self.layerfilter_1)
self.clearBuffers_1 = Qt3DRender.QClearBuffers(self.cameraSelector_1)
self.cameraSelector_1.setCamera(self.camera())
self.clearBuffers_1.setBuffers(Qt3DRender.QClearBuffers.AllBuffers)
# Viewport 2
self.viewport_2 = Qt3DRender.QViewport(self.surselector)
self.layerfilter_2 = Qt3DRender.QLayerFilter(self.viewport_2)
self.layer_2 = Qt3DRender.QLayer(self.entity_2)
self.entity_2.addComponent(self.layer_2)
self.layer_2.setRecursive(True)
self.layerfilter_2.addLayer(self.layer_2)
self.cameraSelector_2 = Qt3DRender.QCameraSelector(self.layerfilter_2)
self.clearBuffers_2 = Qt3DRender.QClearBuffers(self.cameraSelector_2)
self.cameraSelector_2.setCamera(self.camera())
# The line below causes that no entity appears
self.clearBuffers_2.setBuffers(Qt3DRender.QClearBuffers.AllBuffers)
# The code below is what make viewport 2 / layer 2 / layerfilter 2 different from view port 1 / etc.
self.rendstate_2 = Qt3DRender.QRenderStateSet(self.clearBuffers_2)
self.rendstate_2.setParent(self.clearBuffers_2)
depth = Qt3DRender.QDepthTest()
depth.setDepthFunction(Qt3DRender.QDepthTest.LessOrEqual)
self.rendstate_2.addRenderState(depth)
self.setActiveFrameGraph(self.surselector)
If I understand correctly you want both viewports be drawn over each other (i.e. not in left and right half), while the first one draws all normal entities and the second one the ones that are always visible.
First of all, I think you don't need the viewports. Qt defaults this to the rectangle (0, 0, 1, 1) if none is present, but I'm not sure about this.
The actual issue is this line
self.clearBuffers_2.setBuffers(Qt3DRender.QClearBuffers.AllBuffers)
because here you delete the color buffer as well, which deletes everything the first viewport rendered. Try setting it to Qt3DRender.QClearBuffers.DepthBuffer. This only clears your depth buffer.The entites of the second viewport will be drawn ontop of the rendering of the first viewport.

Error using checkmouse

I'm trying to use checkmouse in order to undraw something from my window. When someone clicks the button it should undraw the text and write something else. I'm using checkMouse and getX() and getY() to do this but i keep receiving this error that states:
File "C:\Users\User\Documents\python\project2.py", line 71, in panel
if (clicknew.getX()>90 and clicknew.getX()<210) and (clicknew.getY()>35 and clicknew.getY() < 0):
AttributeError: 'NoneType' object has no attribute 'getX'
this code that i have done so far is as follows:
from graphics import *
#creating the game panel window
def panel():
#grey window, with coordinates flipped, with banners etc
win = GraphWin("Start Panel", 300,200)
win.setCoords(0,0,300,200)
win.setBackground("light grey")
#drawing the BoilerMazer banner with text
boilermazer = Rectangle(Point(0,200),Point(300,160))
boilermazer.setFill("white")
boilermazer.draw(win)
#text inside
banner1 = Text(Point(150,180),"BoilerMazer")
banner1.setStyle("bold")
banner1.setSize(20)
banner1.draw(win)
#initial game panel is going to have two buttons and a top scores object
#top score "screen"
toprec = Rectangle(Point(60,140),Point(240,50))
toprec.setFill("white")
toprec.draw(win)
#text inside toprec
topscores = Text(Point(150,130),"TOP SCORES")
topscores.setSize(8)
topscores.draw(win)
border = Text(Point(150,120),"======")
border.draw(win)
bigmac = Text(Point(150,110),"Big Mac 21")
bigmac.setSize(8)
bigmac.draw(win)
tt = Text(Point(150,90),"T.T 23")
tt.setSize(8)
tt.draw(win)
cshell = Text(Point(150,75),"C-Shell 25")
cshell.setSize(8)
cshell.draw(win)
macmac = Text(Point(150,55),"MacMac 27")
macmac.setSize(8)
macmac.draw(win)
#new player button that will eventually be clicked
new1 = Point(90,35)
new2 = Point(210,0)
newrec = Rectangle(new1,new2)
newrec.setFill("chartreuse2")
newrec.draw(win)
#new player button text
newplayer = Text(Point(150,18),"NEW PLAYER")
newplayer.draw(win)
#reset button
resetrec = Rectangle(Point(240,35),Point(300,0))
resetrec.setFill("red")
resetrec.draw(win)
#resettext
reset = Text(Point(270,18),"RESET")
reset.draw(win)
#secondary panel window is the game panel after they click new player
#set up points that we check between for the new player button first
#setting up the checkmouse
clicknew = win.checkMouse()
if (clicknew.getX()>90 and clicknew.getX()<210) and (clicknew.getY()>35 and clicknew.getY() < 0):
newplayer.undraw()
you can find the graphics window here:http://mcsp.wartburg.edu/zelle/python/graphics.py
I don't understand what I'm doing wrong, is there some other method that I'm supposed to be using? Thanks for your help
According to the docs, checkMouse() returns None if no mouse click has been detected priorly. So that seems to be the case.
You could put a loop around the call to checkMouse and keep checking if clicknew is not None and only in that case go on in your program. But maybe there's a better way...
UPDATE:
Example:
while True:
clicknew = win.getMouse()
if clicknew:
break
else:
time.sleep(0.1) # avoid busy waiting
# clicknew is set now => use it

How to dynamically add/remove widgets from Gtk 3 Window

I am using python3 with Gtk3 and i need to basically remove some widgets from my Gtk.Window and replace them with other widgets when a Gtk.Button is clicked.I have tried using Gtk.ListBoxes with Gtk.ListBoxRows and so far i can remove all the Rows from the ListBox but when i try to add them back,essentially nothing happens.This is part of my code:
def left_view(self, box):
listbox = box
row0 = Gtk.ListBoxRow()
row0.set_halign(Gtk.Align.START)
listbox.add(row0)
#Adding HorizontalBox to place widgets
hbox = Gtk.Box(spacing=10,orientation=Gtk.Orientation.HORIZONTAL)
row0.add(hbox)
prod_name = Gtk.Label()
stock_count = Gtk.Label()
prod_name.set_text('Product Name')
stock_count.set_text('Stock ')
self.prod_name_input = Gtk.Entry()
self.stock_count_input = Gtk.Entry()
#Packaging 101
hbox.pack_start(prod_name, True, True, 0)
hbox.pack_start(self.prod_name_input, True, True, 0)
hbox.pack_start(stock_count, True, True, 0)
hbox.pack_start(self.stock_count_input, True, True, 0)
the function will be given a Gtk.ListBox as the argument.And what i have so far when trying to remove() and add() things to the listbox is:
def remover(self,widget):
vbox = widget.get_parent()
base = vbox.get_parent()
children = base.get_children()
listbox = children[1]
for row in listbox.get_children():
listbox.remove(row)
with open('product_info.json', 'r') as d:
data = d.read()
j = json.loads(data)
d.close()
self.keys = list(j.keys())
row0 = Gtk.ListBoxRow()
listbox.add_child(row0)
scrollwindow = Gtk.ScrolledWindow()
scrollwindow.set_hexpand(True)
scrollwindow.set_vexpand(True)
row0.add_child(scrollwindow)
tview = Gtk.TextView()
scrollwindow.add(tview)
textbuffer = tview.get_buffer()
for item in range(0, len(self.keys)):
textbuffer.insert_at_cursor(' %s\t\t %s \n' %(item, self.keys[item]))
By the way,If there is a simpler way of just replacing widgets on the go in PyGObject,please do let me know coz most of the answers that i saw on the related questions where totally useless
I was baffled by this, too. It turned out the created widgets must be explicitly shown with show() or show_all(). In your case:
row0.show_all()
as the last statement.

Python 3-How to composite two pictures by using PIL?

I'm trying using genetic algorithm to generate a picture which consists of triangle pictures.I use Image.blend() function,but the result is too dark and looks so bad.How could I deal with it?
image_config = {
'mode': 'RGBA',
'size': sourceimg.size,
'color': 'black'
}
im = Image.new(**image_config)
for res in self.decode(chrom):
im_tmp = Image.new(**image_config)
draw = ImageDraw.Draw(im_tmp, 'RGBA')
draw.polygon(xy=[res[0], res[1], res[2]], fill=res[3])
im = Image.blend(im, im_tmp, 0.5)
You need composite() or alpha_composite().

How to change current Plot Window Size (in R)

For example. Assume I do:
dev.new(width=5, height=4)
plot(1:20)
And now I wish to do
plot(1:40)
But I want a bigger window for it.
I would guess that the way to do it would be (assuming I don't want to open a new window) to do
plot(1:40, width=10, height=4)
Which of course doesn't work.
The only solution I see to it would be to turn off the window and start a new one. (Which will end my plotting history)
Is there a better way ?
Thanks.
Some workaround could be rather than using dev.new() R function use this function which should work across platform :
dev.new <- function(width = 7, height = 7)
{ platform <- sessionInfo()$platform if (grepl("linux",platform))
{ x11(width=width, height=height) }
else if (grepl("pc",platform))
{ windows(width=width, height=height) }
else if (grepl("apple", platform))
{ quartz(width=width, height=height) } }
Here is a my solution to this:
resize.win <- function(Width=6, Height=6)
{
# works for windows
dev.off(); # dev.new(width=6, height=6)
windows(record=TRUE, width=Width, height=Height)
}
resize.win(5,5)
plot(rnorm(100))
resize.win(10,10)
plot(rnorm(100))

Resources