I have a database with two columns: ID, Color (1, "red", 2 , "green", etc.) and I am trying to dynamically display the list of the colors with a Checkbox next to the description.
Is this possible?
This is what I am trying to do dynamically rather than static.
import PySimpleGUI as sg
layout =[[sg.Checkbox('DB RED', key='-DB ID 1-')],
[sg.Checkbox('DB GREEN', key='-DB ID 2-')],
[sg.Checkbox('DB BLUE', key='-DB ID 3-')]]
window = sg.Window('Test Window', layout)
event, values = window.read()
window.close()
Thanks for any assistance.
Quick and dirty:
import PySimpleGUI as sg
db_values = [
'DB RED', 'DB GREEN', 'DB BLUE'
]
layout = []
cnt = 1
for entry in db_values:
layout.append([sg.Checkbox(entry, key=f'-DB ID {cnt}-')])
cnt += 1
window = sg.Window('Test Window', layout)
event, values = window.read()
window.close()
Related
I have a Row that contains images and texts, all text widgets should fill all available spaces in the row except the last one. If the last Text doesn't fit the screen it should be shorted to three dots(TextOverflow.ellipsis).
I have this solution:
List<Widget> widgets = [];
for (var item in listItems) {
widgets.add(Image.asset("images/image.png", width: 10.0, height: 10.0));
widgets.add(Flexible(child:Padding(padding: EdgeInsets.only(right: 8.0),child:Text(item.text, style: captionStyle, overflow:TextOverflow.ellipsis))));
}
//then
Expanded(child:new Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: widgets
),
)
But, it doesn't give needed effect
⁍ - Image
| - Row side
(for better understanding)
widgets are placing in this way - | ⁍ someTex... ⁍ someTex... ⁍ someTex...|
or | ⁍ so... ⁍ so... ⁍ so... ⁍ so... ⁍ so...| if a have a lot of items in the list
I need that widgets will build this way -
|⁍someText ⁍someTex ⁍someTex ⁍ some...| only last widget should be shorted
BTW, i don't know how many items will come to the loop.
Could someone explain how I can short only last widget?
Thanks in advance!
Very simple example, but here only the last text widget is clipped
Row(
children: <Widget>[
Text("Some Text", overflow:TextOverflow.ellipsis),
Text("Some Text", overflow:TextOverflow.ellipsis),
Text("Some Text", overflow:TextOverflow.ellipsis),
Text("Some Text", overflow:TextOverflow.ellipsis),
Text("Some Text", overflow:TextOverflow.ellipsis),
Expanded(child: Text("Some Text", overflow:TextOverflow.ellipsis)),
],
),
So in your case, you need to wrap the last children in Expanded like this:
int count = 1;
for (var item in listItems) {
widgets.add(Image.asset("images/image.png", width: 10.0, height: 10.0));
if(count == listItems.length) widgets.add(Expanded(Flexible(child:Padding(padding: EdgeInsets.only(right: 8.0),child:Text(item.text, style: captionStyle, overflow:TextOverflow.ellipsis))));
else widgets.add(Flexible(child:Padding(padding: EdgeInsets.only(right: 8.0),child:Text(item.text, style: captionStyle, overflow:TextOverflow.ellipsis))));
count++;
}
I'm using objectlistview in wxpython and I am very happy with it until now. I cannot find a way to add an event to the checkbox in my objectlistview. At the moment I have a workaround, the user have to click on a button and then something happens with the checked row. But I would like to make it happen when the user checks the checkbox. It have to toggle a graph in my plot.
A second question I have is how I can uncheck the checkboxes after the user clicked the button (this is for if there isn't a way to solve my first question).
My code (I just copied the necessary lines, because my program is very big)
self.tempmeasurements = ObjectListView(self, wx.ID_ANY, style=wx.LC_REPORT | wx.SUNKEN_BORDER)
self.tempmeasurements.SetColumns(microanalysis_options.TempMeasColumndefs)
self.tempmeasurements.CreateCheckStateColumn(0)
self.addbutton = wx.Button(self, wx.ID_ANY, "Add to plot")
self.rembutton = wx.Button(self, wx.ID_ANY,'Remove from plot')
self.Bind(wx.EVT_BUTTON, self.on_toggle_plotlist, self.addbutton)
self.Bind(wx.EVT_BUTTON, self.on_remove_from_plot,self.rembutton)
def on_toggle_plotlist(self, event):
objectsAddPlotList = self.tempmeasurements.GetCheckedObjects()
pub.sendMessage('MA_ADD_TO_PLOT', Container(origin=self, data=objectsAddPlotList)) #to microanalyse controller
self.tempmeasurements.SetCheckState(objectsAddPlotList,False)
def on_remove_from_plot(self,event):
objectsAddPlotList = self.tempmeasurements.GetCheckedObjects()
pub.sendMessage('MA_REM_FROM_PLOT', Container(origin=self, data=objectsAddPlotList)) # to microanalyse controller
The self.tempmeasurements.SetCheckState(objectsAddPlotList,False) line I tried to use to uncheck the checkboxes after the user clicked the button.
this is how the list looks like:
The key thing is to import OLVEvent and then bind your ObjectListView instance to OLVEvent.EVT_ITEM_CHECKED.
I went ahead and created a simple example:
import wx
from ObjectListView import ObjectListView, ColumnDefn, OLVEvent
class Results(object):
""""""
def __init__(self, tin, zip_code, plus4, name, address):
"""Constructor"""
self.tin = tin
self.zip_code = zip_code
self.plus4 = plus4
self.name = name
self.address = address
class MyPanel(wx.Panel):
""""""
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.test_data = [Results("123456789", "50158", "0065", "Patti Jones",
"111 Centennial Drive"),
Results("978561236", "90056", "7890", "Brian Wilson",
"555 Torque Maui"),
Results("456897852", "70014", "6545", "Mike Love",
"304 Cali Bvld")
]
self.results_olv = ObjectListView(self,
style=wx.LC_REPORT|wx.SUNKEN_BORDER)
self.results_olv.Bind(OLVEvent.EVT_ITEM_CHECKED, self.on_item_checked)
self.set_results()
mainSizer.Add(self.results_olv, 1, wx.EXPAND|wx.ALL, 5)
self.SetSizer(mainSizer)
def on_item_checked(self, event):
obj = self.results_olv.GetSelectedObject()
checked = 'Checked' if self.results_olv.IsChecked(obj) else 'Unchecked'
print('{} row is {}'.format(obj.name, checked))
def set_results(self):
""""""
self.results_olv.SetColumns([
ColumnDefn("TIN", "left", 100, "tin"),
ColumnDefn("Zip", "left", 75, "zip_code"),
ColumnDefn("+4", "left", 50, "plus4"),
ColumnDefn("Name", "left", 150, "name"),
ColumnDefn("Address", "left", 200, "address")
])
self.results_olv.CreateCheckStateColumn()
self.results_olv.SetObjects(self.test_data)
class MainFrame(wx.Frame):
""""""
def __init__(self):
"""Constructor"""
title = "OLV Checkbox Tutorial"
wx.Frame.__init__(self, parent=None, title=title,
size=(600, 400))
panel = MyPanel(self)
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
frame.Show()
app.MainLoop()
My shiny dashboard has checkboxInput and I am trying to align it to right within the title of the box item. For smaller boxes (width of 6) the alignment is proper, however for boxes with width of 12, which ever way I realign the column values, the checkbox input remains at the middle of the box. The code is as follows:
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
skin = "green",
dashboardHeader(
title = "TEST", titleWidth = 225
),
dashboardSidebar(
menuItem("TRENDS", tabName = "vactr", icon = shiny::icon("line-chart"))
),
dashboardBody(
tabItems(
tabItem(
tabName = "vactr",
fluidRow(
box(
width = 12, status = "info", title =
fluidRow(
column(6, "Trend - Usage of space",br(),
div(downloadLink("downloadspacetrend", "Download this chart"), style = "font-size:70%", align = "left")),
column(6,
div(checkboxInput(inputId = "spacetrendcheck", "Add to reports", value = FALSE),style = "font-size:70%",float = "right", align = "right", direction = "rtl"))
),
div(plotOutput("spacetrend"), width = "100%", height = "400px", style = "font-size:90%;"),
uiOutput("spacetrendcomment")
)
)
)
)
)
)
server <- function(input, output, session) {
}
shinyApp(ui = ui, server = server)
I want the "Add to reports" check box to the right end of the box. I tried using float, direction arguments with and without, but not getting the desired output.
There is the following reason for you problem: The header title's width is not set to the whole width of the box. Instead, its width is calculated from the elements it contains. This makes the columns (which are 50% title width) also depend on the elements. Your elements however are not that big, so the resulting div is in itself well divided in two equally large columns, but they together don't span the whole box width.
You can just fix the title width to 100% (box header width), which as a result tells the columns to be that large, whatever their content might be.
This is a one line addition.
Note that the style addition in the code below affects all box titles. But I believe that this is never really a problem.
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
skin = "green",
dashboardHeader(
title = "TEST", titleWidth = 225
),
dashboardSidebar(
menuItem("TRENDS", tabName = "vactr", icon = shiny::icon("line-chart"))
),
dashboardBody(
tabItems(
tabItem(tabName = "vactr",
fluidRow(
box(width = 12, status = "info", title =
fluidRow(
tags$style(".box-title {width: 100%;}"),
column(6, "Trend - Usage of space",br(),
div(downloadLink("downloadspacetrend", "Download this chart"), style = "font-size:70%", align = "left")),
column(6,
div(checkboxInput(inputId = "spacetrendcheck", "Add to reports", value = FALSE),style = "font-size:70%",float = "right", align = "right", direction = "rtl"))
),
div(plotOutput("spacetrend"), width = "100%", height = "400px", style = "font-size:90%;"),
uiOutput("spacetrendcomment")
)
)
)
)
)
)
server <- function(input, output, session) {}
shinyApp(ui = ui, server = server)
I set the textArea setGrowByContent true and setGrowLimit to 2, but there is always only one row. So i twisted the code and increase the
height of textArea by twice if the size of textArea is greater than Button size. Below is the codes. My issue is at the end of the question:
Button homeButtonn = new Button(btnIcon){
#Override
protected Dimension calcPreferredSize() {
System.out.println("Button size: " + super.calcPreferredSize());
return super.calcPreferredSize();
}
#Override
public void setUIID(String id) {
super.setUIID("homeButtonn");
}
};
TextArea buttonTitle = new TextArea(title){
#Override
protected Dimension calcPreferredSize() {
System.out.println("textArea title: " + getText());
System.out.println("Textarea size: " +super.calcPreferredSize());
System.out.println("");
return super.calcPreferredSize();
}
};
buttonTitle.setUIID("smallLabel");
buttonTitle.getAllStyles().setAlignment(Label.LEFT);
zeroPaddingMargin(buttonTitle);
if (buttonTitle.getPreferredW() -10 > homeButtonn.getPreferredW()) {
buttonTitle.setPreferredH(buttonTitle.getPreferredH() * 2);
}
buttonTitle.setPreferredW(homeButtonn.getPreferredW() - 10);
buttonTitle.getAllStyles().setMargin(3, 3, 3, 3);
buttonTitle.setEditable(false);
buttonTitle.setGrowByContent(true);
buttonTitle.setGrowLimit(2);
buttonTitle.setScrollVisible(false);
gridContainer.add(LayeredLayout.encloseIn(homeButtonn, FlowLayout.encloseRightBottom(buttonTitle)));
OUTPUT:
Button size: width = 146 height = 140
textArea title: DJ and Sound
Textarea size: width = 194 height = 25
Here textArea size is greater than button size but if i set size of the textArea with exact size of button,
it fits well. So how can textArea size be greater than button size and also all texts of textArea fits well inside button?
The problem i got is that since textArea size is greater than button size, the height of textArea is multiplied by twice its own height but
textArea fit well in single line and it leaves extra line/row below.
PS see the screenshot. Thankyou
without calcPreferred size or preferredSize:
If calcPreferredSize is removed, it takes whole screenwidth though it is in gridlayout with 3 column
Update:
Recent Code without calcPreferredSize & textArea nested in a container too
GridLayout gl2 = new GridLayout(counter / 3 + 1, 3);
gl2.setAutoFit(true);
Container gridContainer = new Container(gl2);
gridContainer.setScrollableY(true);
f.addComponent(gridContainer);
imageUrl = entry.get("img").toString();
title = entry.get("name").toString();
homePlaceholder = homePlaceholder.scaled(screenWidth / 3 - 20, screenWidth / 3 - 26);
encodedHomePlaceholder = EncodedImage.createFromImage(homePlaceholder, true);
Image btnIcon = URLImage.createToStorage(encodedHomePlaceholder, "home_" + title + imageUrl, allUrl.globalHomeImageUrl + imageUrl, URLImage.RESIZE_SCALE_TO_FILL);
homeButton.setIcon(btnIcon);
TextArea buttonTitle = new TextArea(title);
buttonTitle.getAllStyles().setAlignment(Label.LEFT);
buttonTitle.getAllStyles().setMargin(3, 3, 3, 3);
buttonTitle.setEditable(false);
buttonTitle.setGrowByContent(true);
buttonTitle.setGrowLimit(2);
buttonTitle.setScrollVisible(false);
Container btnTitleContainer = new Container();
btnTitleContainer.addComponent(buttonTitle);
gridContainer.add(LayeredLayout.encloseIn(homeButton, FlowLayout.encloseRightBottom(btnTitleContainer)));
f.revalidate();
Don't use calcPreferredSize, setPreferred* or any such API when you want something to be automatically calculated.
By definition you are disabling the automatic calculation when you are using these APIs that is why most of those API's are deprecated.
You need to only use layout logic.
What ever i did to make it right in layer layout and textarea, it didnt work so i tried other things and it work. I set the bg image of the container with border layout & keep the textarea in the south of borderlayout.
homePlaceholder = homePlaceholder.scaled(screenWidth / 3, screenWidth / 3);
encodedHomePlaceholder = EncodedImage.createFromImage(homePlaceholder, true);
Image btnIcon = URLImage.createToStorage(encodedHomePlaceholder, "home_" + title + imageUrl, allUrl.globalHomeImageUrl + imageUrl, URLImage.RESIZE_SCALE_TO_FILL);
Container innerContainer = new Container(new BorderLayout());
innerContainer.getAllStyles().setBgImage(btnIcon);
innerContainer.getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED);
gridContainer.add(innerContainer);
TextArea buttonTitle = new TextArea(properCase(title));
buttonTitle.setUIID("smallLabel");
zeroPaddingMargin(buttonTitle);
innerContainer.add(BorderLayout.SOUTH,buttonTitle);
buttonTitle.setEditable(false);
buttonTitle.setGrowByContent(true);
buttonTitle.setGrowLimit(2);
buttonTitle.setScrollVisible(false);
gridContainer.revalidate();
I would like to know how the XtraGrid and the BandedGrid play togehter and are bound to the underlaying data. The documentation has some explanatory tl;dr-text but i am missing a full working example to set it up in code. So it took me about 2 hours to figure it out. Based on this blog entry
i would like to post my answer here.
If there is a better way to put the pieces together as in my answer below i would love to know about it.
First you have to know that you can bind a plain DataTable to the XtraGrid and that the creation of the banded grid is independent.
Below you can see a new instance of XtraGrid is created. It MainView is set to be a BandedGridView
private void LoadAndFillXtraGrid() // object sender, EventArgs e
{
grid = new DevExpress.XtraGrid.GridControl();
grid.Dock = DockStyle.Fill;
// set the MainView to be the BandedGrid you are creating
grid.MainView = GetBandedGridView();
// set the Datasource to a DataTable
grid.DataSource = GetDataTable();
// add the grid to the form
this.Controls.Add(grid);
grid.BringToFront();
}
Above the line grid.MainView = GetBandedGridView(); set a BandedGridView as the MainView of the Xtragrid. Below you see how to create this BandedGridView
//Create a Banded Grid View including the grindBands and the columns
private BandedGridView GetBandedGridView()
{
BandedGridView bandedView = new BandedGridView();
// Set Customer Band
SetGridBand(bandedView, "Customer",
new string[3] { "CustomerId", "LastName", "FirstName" });
SetGridBand(bandedView, "Address", new string[3] { "PLZ", "City", "Street" });
return bandedView;
}
To set up the GridBand you have to create a GridBand and attach it to the bandedGridView by calling bandedView.Columns.AddField for each column
private void SetGridBand(BandedGridView bandedView, string gridBandCaption
, string[] columnNames)
{
var gridBand = new GridBand();
gridBand.Caption = gridBandCaption;
int nrOfColumns = columnNames.Length;
BandedGridColumn[] bandedColumns = new BandedGridColumn[nrOfColumns];
for (int i = 0; i < nrOfColumns; i++)
{
bandedColumns[i] = (BandedGridColumn)bandedView.Columns.AddField(columnNames[i]);
bandedColumns[i].OwnerBand = gridBand;
bandedColumns[i].Visible = true;
}
}
The DataSource can be a plain DataTable that contains some columns. If the name of the column in the datatable matches the names of the BandedGridColumn the will be automatically mapped. As you can see i added a column NotMapped in the datatable which is not visible in the screenshot above:
private DataTable GetDataTable()
{
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[] {
new DataColumn("CustomerId", typeof(Int32)),
new DataColumn("NotMapped", typeof(Int32)),
new DataColumn("LastName", typeof(String)),
new DataColumn("FirstName", typeof(String)),
new DataColumn("PLZ", typeof(Int32)),
new DataColumn("City", typeof(String)),
new DataColumn("Street", typeof(String))
});
dt.Rows.Add(1, 0, "John", "Barista", 80245, "Manhatten", "Broadway");
dt.Rows.Add(2, 0, "Mike", "Handyman", 87032, "Brooklyn", "Martin Luther Drive");
dt.Rows.Add(3, 0, "Jane", "Teacher", 80245, "Manhatten", "Broadway 7");
dt.Rows.Add(4, 0, "Quentin", "Producer", 80245, "Manhatten", "Broadway 15");
return dt;
}
If someone has a more elegant way to put the pieces together i would love to know about it.