canvas.create_window not working? - user-interface

I want to place a widget in my canvas.
I have written the following function to create a button and display it.
in the center of the x coordinate of my canvas.
def Button_Placer():
label1=Label(canvas, width =20, height = 2, font = font2, text="")
label1.pack()
def Show_Name():
name=NameGenerator()
label1.config(text=name)
button1=Button(canvas, text="Generate Name", width=20, height=4, font=font1, command=Show_Name)
button1=canvas.create_window(250, 300)
I have also created a canvas at the top:
canvas = Canvas(root, width=500, height = 500, bg="red")
canvas.pack()
Unfortunately the canvas.create_window does not work. .pack() works however is not what i need. I have looked at other examples however they are all off OOP and therefore do not find it relevant for my understanding.

As #CommonSense writes, try canvas.create_window(200, 200, window=button1).
Also; you create label1 inside a function and when the functioin exits the name label1 will be garbage collected.
When you create widgets on canvas the reference is an integer; the index of that widget on the canvas. If you use the widget name as reference for the canvas widget you lose the reference to the actual widget.
Try the example below:
from tkinter import *
root = Tk()
canvas = Canvas(root, width=500, height=500, bg="red")
canvas.pack()
def Show_Name():
name = 'A name' # No function NameGenerator()
label1.config(text=name)
button1 = Button(canvas, text="Generate Name", width=20, height=4,
command=Show_Name)
canvas_button1 = canvas.create_window(250, 300, window=button1)
label1 = Label(canvas, width=20, height=2, text="")
canvas_label1 = canvas.create_window(250, 200, window=label1)

Related

Firemonkey TListBox changing background color at runtime

I there a way, at runtime, other than using styles, to change the background color of a TListBox? Can I use the OnPaint event?
Because the TListbox doesn't have a property to change the background color, I can only think of the following, which is based on combining two components, of which one (the TListBox) uses a built-in style. Note however, that this is not depending on TStyleBook nor any of the style files supplied with Delphi Firemonkey.
Place a TRectangle as a background for the TListBox. Set its Fill - Color property to a color you like. (I used "Cornsilk" in the example).
Place the TListBox on the rectangle as a child of the rectangle. In the "Object Inspector" locate the StyleLookup property and change its value to transparentlistboxstyle. This makes the listbox transparent and the rectangle and its fill color to shine through.
If you make the TListBox one pixel smaller than the rectangle on each side, you can use the Sides property to provide a thin frame around the listbox. Or you can choose to make them equally sized and not show any frame.
My test result looks like this:
The TRectangle and the TListbox properties from the .fmx file:
object Rectangle1: TRectangle
Anchors = [akLeft, akTop, akBottom]
Fill.Color = claCornsilk
Position.X = 7.000000000000000000
Position.Y = 40.000000000000000000
Size.Width = 361.000000000000000000
Size.Height = 219.000000000000000000
Size.PlatformDefault = False
object ListBox1: TListBox
Anchors = [akLeft, akTop, akRight, akBottom]
Position.X = 1.000000000000000000
Position.Y = 1.000000000000000000
Size.Width = 359.000000000000000000
Size.Height = 217.000000000000000000
Size.PlatformDefault = False
StyleLookup = 'transparentlistboxstyle'
TabOrder = 0
ParentShowHint = False
ShowHint = False
DisableFocusEffect = True
ItemHeight = 48.000000000000000000
DefaultItemStyles.ItemStyle = 'listboxitemrightdetail'
DefaultItemStyles.GroupHeaderStyle = ''
DefaultItemStyles.GroupFooterStyle = ''
Viewport.Width = 359.000000000000000000
Viewport.Height = 217.000000000000000000
end
end
To change the color of ListBox1, you actually change the color of the TRectangle:
procedure TForm5.ColorListBox1ItemClick(const Sender: TCustomListBox;
const Item: TListBoxItem);
begin
Rectangle1.Fill.Color := TColorListBox(Sender).Color;
end;

Unable to update TKinter graph

Colleagues,
I am designing a GUI with two buttons and one is to display a graph, hourly temperature.
The issue that I am facing is that I can not make a function(update_graph) that updates the value with self.after.
This part creates page 1 and i working fine, until I call update_graph
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page One!!!", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
button2 = tk.Button(self, text="Page Two",
command=lambda: controller.show_frame(PageTwo))
button2.pack()
canvas = Canvas(self, width=400, height=400, bg = 'white')
canvas.pack()
# create x and y axes
canvas.create_line(100,250,400,250, width=2)
canvas.create_line(100,250,100,50, width=2)
# creates divisions for each axle
for i in range(11):
x = 100 + (i * 30)
canvas.create_line(x,250,x,245, width=2)
canvas.create_text(x,254, text='%d'% (10*i), anchor=N)
for i in range(6):
y = 250 - (i * 40)
canvas.create_line(100,y,105,y, width=2)
canvas.create_text(96,y, text='%5.1f'% (50.*i), anchor=E)
self.update_graph()
def update_graph(self):
# here is canvas create line that causes a trouble
canvas.create_line(100,250,140,200, width=2)
self.after(100,self.update_graph)
Whith this code I get an error "canvas is not defined".
If I add self to canvas in update_graph, I get
self.canvas.create_line(100,250,140,200, width=2)
AttributeError: 'PageOne' object has no attribute 'canvas'
What am I missing here?
canvas is only defined in the scope of the constructor (__init__) method. If you want to be able to access it elsewhere in the class, you need to make it an instance variable. Instead of,
canvas = Canvas(self, width=400, height=400, bg = 'white')
make it,
self.canvas = Canvas(self, width=400, height=400, bg = 'white')
now, everywhere else in the code where you reference canvas, change it to self.canvas. This should fix the problem.
On an unrelated note, a problem that I'm seeing in update_graph is that it calls itself recursively, or over and over. Perhaps you could change it to something like this:
def update_graph(self):
# This line is quite long. Maybe you could shorten it?
self.after(100, lambda: canvas.create_line(100,250,
140,200, width=2))
Hope this helps!
EDIT: My redefinition of update_graph only makes sense if you want one fixed line drawn. If you intend to add other functionality, such as periodic updates, the original code is correct, as Bryan pointed out.

How to make button with image and determine CGSize in sprite kit swift

How can I create a button with an image so I can still decided the CGSize myself. Right now I can only do this.
let playNode = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 100, height: 44))
playNode.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));
playNode.name = "play"
addChild(playNode)
I would like to replace the red color with an actual image. So far I haven't found a way how to actual create a button with an image AND decide its CGSize. I do know how to create a button just with an image, but I can't determine its CGSize then. Any help would be appreciated !
You can set the size property of your node after you've set the image. Like that:
let playNode = SKSpriteNode(imageNamed: "yourImage")
//Set it after you've set the image.
playNode.size = CGSizeMake(200, 200)
playNode.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
playNode.name = "play"
addChild(playNode)

Creating a fixed background using tkinter

I am using tkinter when and trying to set up a window with a background image. In some of the processes I have a frame that fills up with checkboxes so I created a scrollbar so the user can see all the options. The problem is the scroll bar also moves the background image of the canvas. Is there a way I can fix the image to not move or somehow move the frame by itself.
code is
def canvasScroll():
canvas = gui.createCanvas()
fFrame = gui.createNewFrame()
scrollbar = Scrollbar(root, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand = scrollbar.set)
scrollbar.pack(side="right", fill="y")
canvas.pack(side="left", fill="both", expand= True)
canvas.create_window((150,50),window = fFrame, anchor='nw', tags = "frame")
gOb.change_canvas(canvas)
fFrame.bind("<Configure>", gui.scroll)
gOb.change_scrollbar(scrollbar)
gOb.change_frame(fFrame)
def createCanvas():
canvas = Canvas(root,height = _h, width = _w,highlightthickness = 0)
canvas.pack(side='top',fill='both',expand='yes')
canvas.create_image(-200,-200,image=bground,anchor='nw')
return canvas
def createNewFrame():
frame = Frame(root,height = _h, width = _w,background='white')
frame.pack()
return frame
Just to clear things up, these guys are all part of a class name gui and gOb is an object that hold several gui objects.
Here's one idea - it's kind of kludgy, but it would work. Every time the scrollbar scrolls, shift the background image's position so it appears to stay in the same place:
Tag your image so you can access it later:
canvas.create_image(-200,-200,image=bground,anchor='nw',tags="background")
# ^^^^^^^^^^^^^^^^^
Make your scrollbar call a function that you define:
scrollbar = Scrollbar(root, orient="vertical", command=scrollCallback)
Define your scroll callback:
def scrollCallback(*args):
canvas.yview(*args)
# Arrange for your background image to move so it appears to stay in the same position as the canvas scrolls.

Matlab, GUI, Scrolling content in Pane. How to hide overflow?

I am trying to make a Matlab GUI that has a panel with scrolling content inside of a larger figure. I am having a problem hiding the overflow content when it scrolls out of the subpanel.
I got the code for the scrollbar from this SO post: Adding scroll bar in subplots within GUI
Try the code below. I have a figure, an outer panel (smaller than the figure, child to the figure), a scrolling panel (with a height greater than the figure, child to outer panel), a scroll bar, and a text field to appear in the scrolling pane (child to the scrolling panel).
When you try the code you will see the text string, which is just the alphabet repeated, scrolls up and down the whole length of the figure, but the scrolling panel stops at the edge of the limits of the outer panel.
How can I correct this problem. Thanks.
function guitest
scrsz = get(0,'ScreenSize');
height = scrsz(4)*7/8;
width = scrsz(3)*2/3;
leftmargin = 10;
rightmargin = 10;
% figure
handles.hFig = figure('Visible','on',...
'Position', [scrsz(3)/8 scrsz(4)/10 width height],...
'Name', 'Tap Toolbar Report',...
'NumberTitle', 'off',...
'Color', [0.75 0.75 0.75],...
'ToolBar','none',...
'MenuBar','none',...
'Resize','off');
% subpanel in the figure for scrolling
handles.hOut = uipanel('Parent',handles.hFig,...
'BackgroundColor', [0.85 0.85 0.85],...
'BorderWidth', 0,...
'Units', 'pixels',...
'Position',[leftmargin 100 width-2*leftmargin height-200]);
hPanheight = 2000;
handles.hPan = uipanel('Parent',handles.hOut,...
'BackgroundColor', [0.85 0.85 0.85],...
'BorderWidth', 0,...
'Units', 'pixels',...
'Position',[0 0 width-2*leftmargin-19 hPanheight]);
str = sprintf('a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nx\ny\nz\na\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nx\ny\nz\na\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nx\ny\nz\na\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nx\ny\nz\na\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nx\ny\nz\na\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nx\ny\nz\na\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nx\ny\nz\na\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nx\ny\nz');
uicontrol('Parent', handles.hPan,'Style','text','String',str,'FontSize', 10,'FontWeight','bold', 'HorizontalAlignment', 'left',...
'Position',[10 20 20 1960],'BackgroundColor', [0.85 0.85 0.85]);
handles.hSld = uicontrol('Style', 'slider',...
'BackgroundColor', [0.8 0.8 0.8], ...
'Position', [width-leftmargin-20 101 19 height-202],...
'Callback', {#onSlide,handles.hPan,handles.hOut});
set(handles.hSld,'Value',1);
onSlide(handles.hSld,'',handles.hPan,handles.hOut)
end
function onSlide(hSld,~,hPan,hOut)
%# slider value
offset = get(hSld,'Value');
%# update panel position
p = get(hPan, 'Position'); %# panel current position
ph = get(hOut, 'Position');
set(hPan, 'Position',[p(1) -offset*(p(4)-ph(4)) p(3) p(4)])
end
I would use a container object that has scroll capability built-in. Take a look at:
help uitable
help uitree

Resources