wxPython widget not centered vertically - checkbox

I am trying to center a CheckBox widget vertically inside a panel. I cannot figure out why it's aligned to the top.
I had to create a Panel for the CheckBox because without that the background looks ugly (Windows 10 -- see second image)
Thanks for suggestions!
class wxUIE(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, size=(800, 400), title=title)
self.editorText = wx.TextCtrl (self, style=wx.TE_MULTILINE+wx.SUNKEN_BORDER+wx.TE_BESTWRAP)
self.myBar = wx.TextCtrl (self, -1)
# Checkbox
self.myCheckBoxPanel = wx.Panel(self, size=(-1, 25))
self.myCheckBox = wx.CheckBox(self.myCheckBoxPanel, label="Highlight", style=wx.ALIGN_CENTER_VERTICAL)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.editorText, 1, wx.EXPAND)
self.sizer.Add(self.sizer2, 0, wx.EXPAND)
self.sizer2.Add(self.myBar, 10, wx.EXPAND)
self.sizer2.Add(self.myCheckBoxPanel, 0, wx.EXPAND)
self.SetSizeHints(800,400)
self.SetSizer(self.sizer)
self.SetAutoLayout(True)
self.Show()
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = wxUIE(None, "My Edit Control")
frame.Show()
app.MainLoop()
CheckBox aligned to top of panel
CheckBox is aligned vertically correctly but the background sucks.

Related

The hidden wx.Frame is shown automatically and can not be hidden after restoring from minimize

Python 3.7+wxPython 4.0.6 (same as 4.0.2)+windows 10 (64-bit)
Because I need a sub frame which can floating on main frame, so use style: wx.FRAME_FLOAT_ON_PARENT.
Operations: First open the sub frame, then minimize the main frame. After restoring from minimize, hide the sub frame (using Hide()). Then minimize->restore again. The sub frame is shown automatically, and can not be hidden.
I have tested that at this time, frame.IsShown() returns False.
Sample as follows.
import wx
class MainFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, id=-1, parent=parent, size=wx.Size(600, 500),
title='Test')
self.panel = wx.Panel(self, id=-1, pos=(200, 300))
self.button = wx.Button(self.panel, id=-1, label='button',
pos=wx.Point(20, 56), size=wx.Size(87, 28))
self.button.Bind(wx.EVT_BUTTON, self.OnButton, id=-1)
self.frame = MyFrame(self)
def OnButton(self, event):
self.frame.Show()
event.Skip()
class MyFrame(wx.Frame):
def __init__(self, parent):
style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | \
wx.MINIMIZE_BOX | wx.FRAME_NO_TASKBAR | wx.FRAME_FLOAT_ON_PARENT
wx.Frame.__init__(self, id=-1, parent=parent, size=wx.Size(300, 200),
title='Sub', style=style)
self.Bind(wx.EVT_CLOSE, self.OnClose)
def OnClose(self, evt):
self.Hide()
if __name__ == '__main__':
app = wx.App()
frame = MainFrame(None)
frame.Show()
app.MainLoop()
I do not need to close the sub frame. I need to hide it.
The detail operations are:
Click the button to open the sub frame.
Click the minimize button of the main frame. (-> All the frames are minimized.)
Click the icon in taskbar to restore the main frame.
Click the "×" button of the sub frame.
Click the minimize button of the main frame again.
Click the icon in taskbar to restore the main frame.
-> Problem: the sub frame is shown. And can not use "×" button to hide it.
I need the sub frame shown on main frame when it loses focus, so I used wx.FRAME_FLOAT_ON_PARENT.
Any advice?
I cannot reproduce the behavior you describe using wxPython 4.0.4, python 3.7 and macOS. But anyway, I do not think that you will be able to close MyFrame using the GUI because you are modifying the normal behavior of the wx.EVT_CLOSE event and do not include self.Destroy() or equivalent in the MyFrame.OnClose method. With your code, the only way to close MyFrame is to close the MainFrame because you make MyFrame a child of MainFrame.
Nevertheless, with your code, if MyFrame is minimized then I cannot see it again by pressing the button. I changed your code a little bit and now I can hide/minimize and then show/restore MyFrame. I needed to remove wx.FRAME_FLOAT_ON_PARENT for the Restore() method to properly work. Hope this helps.
import wx
class MainFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, id=-1, parent=parent, size=wx.Size(600, 500),
title='Test')
self.panel = wx.Panel(self, id=-1, pos=(200, 300))
self.button = wx.Button(self.panel, id=-1, label='button',
pos=wx.Point(20, 56), size=wx.Size(87, 28))
self.button.Bind(wx.EVT_BUTTON, self.OnButton, id=-1)
self.frame = MyFrame(self)
def OnButton(self, event):
if self.frame.IsShown():
self.frame.Restore()
else:
self.frame.Show()
class MyFrame(wx.Frame):
def __init__(self, parent):
style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | \
wx.MINIMIZE_BOX | wx.FRAME_NO_TASKBAR
wx.Frame.__init__(self, id=-1, parent=parent, size=wx.Size(300, 200),
title='Sub', style=style)
self.Bind(wx.EVT_CLOSE, self.OnClose)
def OnClose(self, evt):
self.Hide()
if __name__ == '__main__':
app = wx.App()
frame = MainFrame(None)
frame.Show()
app.MainLoop()

textArea growByContent doesnt work in layer layout

I used layer layout to keep the title ie textArea on top of button image. But i cannot grow textArea size. Also the padding and margin on the textArea is not working as well.
Image btnIcon = URLImage.createToStorage(placeholder, "homeIcon" + imageUrl, allUrl.globalHomeImageUrl + imageUrl, URLImage.RESIZE_SCALE);
int width = placeholder.getWidth();
int height = placeholder.getHeight();
homeButton.setPreferredSize(new Dimension(width, height));
homeButton.getAllStyles().setBgImage(btnIcon);
TextArea buttonTitle = new TextArea(title);
buttonTitle.setRows(1);
buttonTitle.setUIID("smallLabel");
buttonTitle.getAllStyles().setPadding(0, 0, 0, 0);
buttonTitle.getAllStyles().setMargin(0, 4, 0, 4);
buttonTitle.setPreferredW(screenWidth / 3 - 30);
buttonTitle.setEditable(false);
buttonTitle.setGrowByContent(true);
buttonTitle.setIsScrollVisible(false);
buttonTitle.setGrowLimit(2);
Container container1 = new Container();
container1.setUIID("buttonTitleContainer");
container1.getAllStyles().setMargin(0, 5, 0, 0);
container1.getAllStyles().setBgTransparency(0);
container1.add(LayeredLayout.encloseIn(homeButton, FlowLayout.encloseRightBottom(buttonTitle)));
middleContainer.addComponent(BorderLayout.CENTER, container1);
How can i grow the textArea row as required and set the padding margin of the textarea.
Update:
i commented setPreferredW() and added calcPreferredSize() to set the dimension but how can i set the height dynamically??
TextArea buttonTitle = new TextArea(title){
#Override
protected Dimension calcPreferredSize() {
Dimension d = new Dimension(screenWidth/3-10, 40);
return d; //To change body of generated methods, choose Tools | Templates.
}
};
buttonTitle.setUIID("smallLabel");
buttonTitle.getAllStyles().setAlignment(Label.LEFT);
buttonTitle.setRows(1);
buttonTitle.getAllStyles().setPadding(0, 0, 0, 0);
buttonTitle.getAllStyles().setMargin(0, 0, 0, 4);
// buttonTitle.setPreferredW(screenWidth / 3 - 30);
buttonTitle.setEditable(false);
buttonTitle.setGrowByContent(true);
buttonTitle.setIsScrollVisible(false);
buttonTitle.setGrowLimit(2);
buttonTitle.setScrollVisible(false);
the design is somewhat like below:
Current screenshot:
As you can see, there is only one word displayed and the textArea always has only 1 row and doesnt grow
The problem isn't in the LayeredLayout it's due to the fact that you called the deprecated setPreferredW.
Notice that setPreferredW also limits the height.

IronPython - WPF application - Gather User input from GUI (after I close th GUI) and use it in main Python code

I developed an IronPython-wpf application with GUI using XAML. The user enter all the inputs in the GUI and I can save them. My problem is how I could pass those variables to my main python code after USER closes the GUI? To close the GUI, I have a button, which closes the GUI, If the USER click it.
What I did is as follows (I just copied some portion of the code):
import wpf
class MyApp(Window):
def __init__(self):
self.opencfgfile()
self.ictemp = self.FindName('pipent')
self.ictemp.Text = self.ictest
self.button = self.FindName('button')
self.button.Click += self.onClick
def onClick(self, sender, event):
self.Close()
def opencfgfile(self):
sstest = os.environ['test']
infile = open (sstest + '\config\test_Config.cfg' , 'r')
for line in infile:
if line != "\n":
line = line[:-1]
fields = line.split('=')
if fields[0] == 'Initial test ID ':
self.ictest = fields[1].lstrip()
def getsetname(self):
try:
return self.ictemp
except AttributeError:
return
if __name__ == "__main__":
c = MyApp()
Application().Run(c)
iset = c.getsetname()
In my class, if I put a break point, self.ictest has a value of 'test' and self.ictemp has a value of {System.Windows.Controls.TextBox:test}, however if I put the break point in my main program for iset, I will get this Value: 'The name iset does not exist in the current context. I really appreciate if you can help me on this issue.
Your problem is, that the code iset = c.getsetname() will only be reached, after the main window is closed. The reason for this is, that Application().Run() contains your "application main loop", which will run until the main window is closed. So in your case, you should implement all interaction logic in MyApp, not in the application entry point. Everything under if __name__ == "__main__" should only be used for initializing some modules or similar things.
If you want to encapsulate some logic, put it in own modules and call it from MyApp. For example if you want to react on some button click, just do this:
# Short
def __init__(self, ...):
# Init component
self.yourButton.Click += self.OnButtonClick
def OnButtonClick(self, sender, args):
MessageBox.Show("Clicked on some button!") # Import Message box before :)
Hope this helps.
EDIT
This is working pretty well:
import wpf
from System.Windows import Window, Application
from System.Windows.Controls import TextBox
class MyApp(Window):
box = None
def __init__(self):
self.Width = 200
self.Height = 200
self.box = TextBox()
self.box.Height = 24
self.box.Width = 150
self.Content = self.box
def getBoxContent(self):
return self.box.Text
if __name__ == "__main__":
c = MyApp()
Application().Run(c)
print (c.getBoxContent())
Info passing
If you want to pass info to and from the ui, just create some class which hold the information. This will be the best solution:
import wpf
from System.Windows import Window, Application
from System.Windows.Controls import TextBox
class Information:
InformationOne = 1
InformationTwo = "Hello World"
class MyApp(Window):
box = None
information = None
def __init__(self, info):
self.information = info
self.Width = 200
self.Height = 200
self.box = TextBox()
self.box.Height = 24
self.box.Width = 150
# Init information
self.box.Text = self.information.InformationTwo
self.Content = self.box
# Information property
#property
def Information(self):
self.information.InformationTwo = self.box.Text
return self.information
if __name__ == "__main__":
info = Information()
c = MyApp(info)
Application().Run(c)
# Get information
print (c.Information.InformationTwo)

ios : UIScrollView with UITableView

I want to implement one page with vertical scroll view which contains some Images, Labels and one table view in bottom.
Table may have any number of rows. When user scroll to the top other elements such as images, labels should be hide but table should be visible at the top of screen and only table items should be scrolled.
I have tried by setting the currentoffset of scrollview in method scrollViewDidEndDecelerating but its not such smooth.
Scroll view first goes above, comes down and then set the table at top.
Can you please suggest me what should i implement here?
Thanks.
Try this....
// Add image in scrollView
serviceImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"row.png"]];
[serviceImage setBackgroundColor:[UIColor clearColor]];
serviceImage.frame = CGRectMake(10, 10, 300, 100);
[myScrollView addSubview:serviceImage];
[serviceImage release];
// Add label in scrollView
UILabel *rateLbl = [[UILabel alloc]initWithFrame:CGRectMake(10, 105, 300, 20)];
rateLbl.text = #"Rates";
rateLbl.font = [UIFont boldSystemFontOfSize:17.0];
rateLbl.textColor = [UIColor colorWithRed:244/255.0 green:29/255.0 blue:94/255.0 alpha:1.0];
rateLbl.textAlignment = UITextAlignmentLeft;
rateLbl.backgroundColor = [UIColor clearColor];
[myScrollView addSubview:rateLbl];
[rateLbl release];
// Add table in scrollView
int heightRateTbl;
heightRateTbl = [productType count] * 44;
rateTableView.frame =CGRectMake(10, expectedLabelSize.height + expectedDecLblSize.height + heightDayTbl + 555, 300, heightRateTbl);
rateTableView.scrollEnabled = NO;
rateTableView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[rateTableView reloadData];
You can enable or disable scroll according your choice.
// Set scrollView height
myScrollView.contentSize = CGSizeMake(320, 125 + heightRateTbl);
Do not forget to set delegates and declare all things(in .h file and in .xib file).
Hope i helped.

wxPython using wxTimer : my box doesn't move

I would like to animate a blue box inside a panel, using a wxTimer. But nothing happens
I set up a custom panel class in which i draw the box
I set up a custom frame, which integrates my custom panel
Here my code :
#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
import wx
WHITE_COLOR = (255,255,255)
class AnimationPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.boxParameters = [10,10,60,60]
self.SetBackgroundColour(wx.Colour(*WHITE_COLOR))
self.Bind(wx.EVT_PAINT, self.OnPaint)
timer = wx.Timer(self)
timer.Start(100)
self.Bind(wx.EVT_TIMER, self.OnTimer, timer)
def OnPaint(self, event):
dc = wx.PaintDC(self)
self.paintBox(dc)
def OnTimer(self, event):
self.boxParameters[0] += 3
self.Update()
def paintBox(self, dc):
dc.SetBrush(wx.Brush("blue"))
dc.DrawRectangle(*self.boxParameters)
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Box with far and back movement", size=(300,200))
AnimationPanel(self)
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MainFrame()
frame.Show(True)
app.MainLoop()
Thanks in advance
You are missing a couple of things. First is that the wx.Timer is going out of scope once you've reached the end of the init method, so it's destroyed before it even gets to do anything. Next, you want to use Refresh() instead of Update() as Refresh() will mark the rectangle (or the entire screen) as "dirty" and cause it to be repainted. See the docs for more info: http://www.wxpython.org/docs/api/wx.Window-class.html
Here's an updated version that works on my Windows box:
import wx
WHITE_COLOR = (255,255,255)
class AnimationPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.boxParameters = [10,10,60,60]
self.SetBackgroundColour(wx.Colour(*WHITE_COLOR))
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
self.timer.Start(100)
def OnPaint(self, event):
dc = wx.PaintDC(self)
self.paintBox(dc)
def OnTimer(self, event):
self.boxParameters[0] += 3
print self.boxParameters
self.Refresh()
def paintBox(self, dc):
dc.SetBrush(wx.Brush("blue"))
dc.DrawRectangle(*self.boxParameters)
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Box with far and back movement", size=(300,200))
AnimationPanel(self)
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MainFrame()
frame.Show(True)
app.MainLoop()

Resources