I am using Ag grid inside quasar QDialog. When the dialog is displayed and I click the column option menu, the Ag grid pop up menu appears behind QDialog, see the picture below:
is there any way to make the ag grid pop up menu shows in the front of the QDialog?
For reference, I see this commmit in Aggrid code:
https://github.com/xh/hoist-react/commit/25522b12155f551fcf95e32211a6cbb8aae8ea35
This adds z-index: 9999 !important to the css style.
Maybe there are ways to add the style using justpy directly or is there more correct way?
My code to produce the above apps is written in python using JustPy v0.10.5 library.
https://github.com/justpy-org/justpy
import justpy as jp
import pandas as pd
def open_dialog(self, msg):
self.dialog.value = True
wm_df = pd.read_csv('https://elimintz.github.io/women_majors.csv').round(2)
def main():
wp = jp.QuasarPage(title='Negative Keyword Editor')
b1 = jp.QBtn(label='Open dialog', color='primary', a=wp)
b1.on('click', open_dialog)
c3_dialog = jp.QDialog(name='alert_dialog', persistent=False, a=wp, maximized=False, full_width=True, transition_show="slide-up", transition_hide="slide-down")
c4_dialog = jp.QCard(a=c3_dialog)
c5_dialog = jp.QCardSection(a=c4_dialog)
c6_dialog = jp.Div(classes='text-h6', a=c5_dialog, text='アカウントを選択:')
c7_dialog = jp.QCardSection(a=c4_dialog, classes='q-pa-none')
grid_dialog = jp.AgGrid(a=c4_dialog, auto_size=True, style = "height: 60vh; width: 100%")
grid_dialog.load_pandas_frame(wm_df)
grid_dialog.options.columnDefs[0].checkboxSelection = True
grid_dialog.options.columnDefs[0].headerCheckboxSelection = True
grid_dialog.options.columnDefs[0].headerCheckboxSelectionFilteredOnly = True
grid_dialog.options.columnDefs[1].filter = 'agTextColumnFilter'
grid_dialog.options.columnDefs[1].cellStyle = {"textAlign": "left"}
grid_dialog.options.defaultColDef.filter = True
grid_dialog.options.defaultColDef.floatingFilter = True
grid_dialog.options.defaultColDef.enableValue = True
grid_dialog.options.defaultColDef.editable = True
grid_dialog.options.defaultColDef.sortable = False
grid_dialog.options.animateRows = True
grid_dialog.options.enableCharts = True
grid_dialog.options.enableRangeSelection = True
grid_dialog.options.statusBar = {
'statusPanels': [
{'statusPanel': 'agTotalAndFilteredRowCountComponent'},
{'statusPanel': 'agTotalRowCountComponent'},
{'statusPanel': 'agFilteredRowCountComponent' },
{'statusPanel': 'agSelectedRowCountComponent' },
{'statusPanel': 'agAggregationComponent' },
],
}
grid_dialog.options.rowSelection = 'multiple'
grid_dialog.options.sideBar = True
c8_dialog = jp.QCardActions(align='right', a=c4_dialog)
c9_dialog = jp.QBtn(flat=True, label='Cancel', color='primary', v_close_popup=True, a=c8_dialog)
c11_dialog = jp.QBtn(flat=True, label='Download', color='primary', v_close_popup=True, a=c8_dialog)
b1.dialog = c3_dialog
return wp
jp.justpy(main)
I add the required css into the wp.css:
wp.css = """
.ag-menu {z-index: 9999 !important;}
"""
reference:
https://github.com/justpy-org/justpy/blob/master/jpcore/webpage.py#L52
the result looks like below, which shows the ag grid pop up menu above the quasar dialog.
Related
I am building a FLET app, but sometimes I have a datatable which is too large for the frame it is in. For the row I have a scrollbar appearing, but for the column I just don't seem to get it working.
In this code a scrollbar simply does not appear.
import pandas as pd
pd.options.display.max_columns = 100
from services.bag import PCHN
from utils.convertors import dataframe_to_datatable
import flet as ft
def main(page: ft.page):
def bag_service(e):
pc = '9351BP' if postal_code_field.value == '' else postal_code_field.value
hn = '1' if house_number_field.value == '' else house_number_field.value
address = PCHN(pc,
hn).result
bag_container[0] = dataframe_to_datatable(address)
page.update() # This is not updating my bag_table in place though. It stays static as it is.
# define form fields
postal_code_field = ft.TextField(label='Postal code')
house_number_field = ft.TextField(label='House number')
submit_button = ft.ElevatedButton(text='Submit', on_click=bag_service)
# fields for the right column
address = PCHN('9351BP', '1').result
bag_table = dataframe_to_datatable(address)
bag_container = [bag_table]
# design layout
# 1 column to the left as a frame and one to the right with two rows
horizontal_divider = ft.Row
left_column = ft.Column
right_column = ft.Column
# fill the design
page.add(
horizontal_divider(
[left_column(
[postal_code_field,
house_number_field,
submit_button
]
),
right_column(
[
ft.Container(
ft.Row(
bag_container,
scroll='always'
),
bgcolor=ft.colors.BLACK,
width=800,)
],scroll='always'
)
]
)
)
if __name__ == '__main__':
ft.app(target=main,
view=ft.WEB_BROWSER,
port=666
)
I am lost as to what could be the case here. Any help would be much appreciated.
I'm trying to create an interactive filter in Bokeh for a graph representation
The source data come from a graph. The function SpotlightData(G) create the pandas dataframes with node and edge informations.
I need to pass the value from a range slider to the CDSView.
I try using js_on_change with a callback function (but I'm not a JS programmer).
Basically I want to create an array of bool values (evaluating a logical expression) and pass it to the view filter.
This is the code:
mytool = "pan , wheel_zoom , undo , reset"
plot = figure(title="Graph layout demonstration"
, tools=mytool
, width=800
, height=600
, background_fill_color='#efefef'
, toolbar_location = "below")
plot.axis.visible = False
plot.grid.grid_line_color = None
NodeDF , EdgeDF = SpotlightData(Spotlight)
Saldo_maxscale = math.ceil((NodeDF["Saldo"].abs().quantile(q=0.9))/1000)*1000
NodeSource = ColumnDataSource(NodeDF)
EdgeSource = ColumnDataSource(EdgeDF)
BF= BooleanFilter([True]*len(EdgeDF))
NodeView = CDSView(source=NodeSource ,filters=[])
EdgeView = CDSView(source=EdgeSource ,filters=[BF])
days_slider = RangeSlider(title="Dates",start=1,end=31,step=1,value=(1, 31))
callback = CustomJS(args=dict(source=EdgeDF["dt_ref_day"],boolout=BF.booleans), code="""
const data = source;
const s = cb_obj.value[0];
const e = cb_obj.value[1];
for (let i = 0; i < data.length; i++) {
boolout[i] = data[i]>=s && data[i]<=e
}
boolout.change.emit();
""")
days_slider.js_on_change('value', callback)
graph = GraphRenderer()
graph.layout_provider = StaticLayoutProvider(graph_layout=nx.spring_layout(Spotlight))
graph.node_renderer.data_source = NodeSource
graph.edge_renderer.data_source = EdgeSource
graph.node_renderer.view = NodeView
graph.edge_renderer.view = EdgeView
NodeColor = LinearColorMapper(palette = cc.CET_D3, low=(Saldo_maxscale*-1), high=Saldo_maxscale)
graph.node_renderer.glyph = Circle(size="LogSize",fill_color=transform('Saldo', NodeColor))
graph.edge_renderer.glyph = MultiLine(line_alpha=0.5, line_width="LogSize")
plot.renderers.append(graph)
show(column(days_slider, plot))
But nothing change in the visualization despite moving the slider.
Thank you all I'm quite a noob with Bokeh
PS: There is a constraint: In this case I can't run a bokeh server
To give some background, I am attempting to use Python to give some of my users an interface through a third-party program (that already has IronPython embedded) to add, edit, and delete records from a SQL Server database.
I've received good assistance from one member here about Python .NET Winforms so I am attempting to get some more assistance. My goal is to populate a DataGridView (dgv) with records from a table. Seems pretty simple. However, when I run the code, my dgv is just an empty container.
I could use some assistance or better yet, point me in the right direction to find the answer. I am willing to learn.
import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")
clr.AddReference("System.Data")
clr.AddReference("System.Globalization")
from System.Windows.Forms import *
from System.Drawing import *
from System.Data import *
from System.Data.SqlClient import *
from System.Globalization import *
class MyForm(Form):
def __init__(self):
# Setup the form
self.Text = "Calculated Control Limits Form"
self.StartPosition = FormStartPosition.CenterScreen # https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.form.startposition?view=net-5.0
# Create & configure the DataGridView label
self.setupDataGridViewLabel()
# Create, configure, and populate data for the DataGridView
self.setupDataGridView()
self.PopulateDataGridView("SELECT * FROM SPC_CALCULATED_CONTROL_LIMITS")
# Create & configure a line seperator
self.setupSeperator()
# Create & configure a Label to grab the users Employee ID
self.setupEmployeeIDLabel()
# Create & configure a label for the Lower Control Limit Label
self.Load_LCL_Label()
# Create & configure a TextBox for the Lower Control Limit
self.Load_LCL_TextBox()
# Create & configure a label for the Target Mean
self.LoadTargetMeanLabel()
# Create & configure a TextBox for the Target Mean
self.LoadTargetMeanTextBox()
# Create & configure a label for the Upper Control Limit
self.Load_UCL_Label()
# Create & configure a TextBox for the Upper Control Limit
self.Load_UCL_TextBox()
# Create & configure a label for the Comment
self.LoadCommentLabel()
# Create a TextBox for the Comment
self.LoadCommentTextBox()
# Create & configure the button
self.LoadButton()
# Register the event handler
self.button.Click += self.button_Click
self.Size = Size (550, self.button.Bottom + self.button.Height + 15)
#Load the Controls to the Form
self.Controls.Add(self.lblCCL)
self.Controls.Add(self.dgvCCL)
self.Controls.Add(self.button)
self.Controls.Add(self.lblSep)
self.Controls.Add(self.lblEmpID)
self.Controls.Add(self.lblLCL)
self.Controls.Add(self.txtLCL)
self.Controls.Add(self.lblTarget)
self.Controls.Add(self.txtTarget)
self.Controls.Add(self.lblUCL)
self.Controls.Add(self.txtUCL)
self.Controls.Add(self.lblComment)
self.Controls.Add(self.txtComment)
def button_Click(self, sender, args):
self.Close()
def setupDataGridView(self):
self.dgvCCL = DataGridView()
self.dgvCCL.AllowUserToOrderColumns = True
self.dgvCCL.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize
self.dgvCCL.Location = Point(self.lblCCL.Left, self.lblCCL.Bottom + 5)
self.dgvCCL.Size = Size(500, 250)
self.dgvCCL.TabIndex = 3
#self.dgvCCL.ColumnCount = len(headers)
self.dgvCCL.ColumnHeadersVisible = True
def setupSeperator(self):
self.lblSep = Label()
self.lblSep.Size = Size(500, 2)
self.lblSep.BackColor = Color.DarkGray
self.lblSep.BorderStyle = BorderStyle.Fixed3D
self.lblSep.Location = Point(self.dgvCCL.Left, self.dgvCCL.Bottom + 10)
def setupDataGridViewLabel(self):
self.lblCCL = Label()
self.lblCCL.Text = "Calculated Control Limits View"
self.lblCCL.Font = Font(self.Font, FontStyle.Bold)
self.lblCCL.Location = Point(10, 10)
self.lblCCL.BorderStyle = 0 # BorderStyle.None --> https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.borderstyle?view=net-5.0
self.lblCCL.Size = Size(self.lblCCL.PreferredWidth, self.lblCCL.PreferredHeight)
def setupEmployeeIDLabel(self):
self.lblEmpID = Label()
self.lblEmpID.Text = 'login.computeruser.upper()'
self.lblEmpID.Font = Font(self.Font, FontStyle.Bold)
self.lblEmpID.Size = Size(self.lblEmpID.PreferredWidth, self.lblEmpID.PreferredHeight)
self.lblEmpID.Location = Point(self.dgvCCL.Right - self.lblEmpID.Width, self.dgvCCL.Top - 15)
self.lblEmpID.BorderStyle = 0
def Load_LCL_Label(self):
self.lblLCL = Label()
self.lblLCL.Text = 'Lower Control Limit'
self.lblLCL.Size = Size(self.lblLCL.PreferredWidth, self.lblLCL.PreferredHeight)
self.lblLCL.Location = Point(self.lblSep.Left + 65, self.lblSep.Top + 15)
self.lblLCL.BorderStyle = 0
def Load_LCL_TextBox(self):
self.txtLCL = TextBox()
self.txtLCL.Size = Size(100, 50)
self.txtLCL.Location = Point(self.lblLCL.Left, self.lblLCL.Bottom + 3)
def LoadTargetMeanLabel(self):
self.lblTarget = Label()
self.lblTarget.Text = 'Target Mean'
self.lblTarget.Size = Size(self.lblLCL.PreferredWidth, self.lblLCL.PreferredHeight)
self.lblTarget.Location = Point(self.lblLCL.Left + 125, self.lblSep.Top + 15)
self.lblTarget.BorderStyle = 0
def LoadTargetMeanTextBox(self):
self.txtTarget = TextBox()
self.txtTarget.Size = Size(100, 50)
self.txtTarget.Location = Point(self.lblLCL.Left + 125, self.lblLCL.Bottom + 3)
def Load_UCL_Label(self):
self.lblUCL = Label()
self.lblUCL.Text = 'Upper Control Limit'
self.lblUCL.Size = Size(self.lblUCL.PreferredWidth, self.lblUCL.PreferredHeight)
self.lblUCL.Location = Point(self.lblTarget.Left + 125, self.lblSep.Top + 15)
self.lblUCL.BorderStyle = 0
def Load_UCL_TextBox(self):
self.txtUCL = TextBox()
self.txtUCL.Size = Size(100, 50)
self.txtUCL.Location = Point(self.lblTarget.Left + 125, self.lblLCL.Bottom + 3)
def LoadCommentLabel(self):
self.lblComment = Label()
self.lblComment.Text = 'Comment'
self.lblComment.Size = Size(self.lblUCL.PreferredWidth, self.lblUCL.PreferredHeight)
self.lblComment.Location = Point(self.lblSep.Left, 350)
self.lblComment.BorderStyle = 0
def LoadCommentTextBox(self):
self.txtComment = TextBox()
self.txtComment.Multiline = True
self.txtComment.Size = Size(500, 50)
self.txtComment.Location = Point(self.lblSep.Left, self.lblComment.Bottom + 5)
def LoadButton(self):
self.button = Button()
self.button.Size = Size(100, 30)
self.button.Location = Point(self.lblSep.Left, self.txtComment.Bottom + 10)
self.button.Text = "Click Me!"
def PopulateDataGridView(self, selectcommand):
bs = BindingSource()
try:
connectionstring = "YourSQLServerConnectionString"
# Create a new data adapter based on the specified query.
da = SqlDataAdapter(selectcommand, connectionstring)
# Create a command builder to generate SQL update, insert, and delete commands based on selectCommand.
cb = SqlCommandBuilder(da)
# Populate a new data table and bind it to the BindingSource.
dt = DataTable()
Locale = CultureInfo.InvariantCulture
da.Fill(dt)
bs.DataSource = dt
# Resize the DataGridView columns to fit the newly loaded content.
self.dgvCCL.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader)
#String connectionString =
#"Data Source=<SQL Server>;Initial Catalog=Northwind;" +
#"Integrated Security=True";
#// Create a new data adapter based on the specified query.
#dataAdapter = new SqlDataAdapter(selectCommand, connectionString);
#// Create a command builder to generate SQL update, insert, and
#// delete commands based on selectCommand.
#SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter);
#// Populate a new data table and bind it to the BindingSource.
#DataTable table = new DataTable
#{
# Locale = CultureInfo.InvariantCulture
#};
#dataAdapter.Fill(table);
#bindingSource1.DataSource = table;
#// Resize the DataGridView columns to fit the newly loaded content.
#dataGridView1.AutoResizeColumns(
#DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader);
except SqlException:
Messagebox.Show("Something happened.")
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(MyForm())
I have written up a simple UI that requires user to select something from a drop-down list, then using that selection, the code will executes the rest of the stuff
Right now, I am having 2 issues..
1. The 'value' is not exactly returning, as soon as a Format is selected and the OK button is hit... Am I missing something?
2. How can I make my UI closes upon a OK button has been selected?
import maya.cmds as cmds
def mainCode():
...
...
print "UI popping up"
showUI()
print "A format has been selected"
cmds.optionMenu('filmbackMenu', edit = True, value = xxx ) # <-- I want to grab the value from the menu selection and input into this 'value' flag
...
...
def showUI():
if cmds.window("UI_MainWindow", exists = True):
cmds.deleteUI("UI_MainWindow")
cmds.window("UI_MainWindow", title = "User Interface Test", w = 500, h = 700, mnb = False, mxb = False, sizeable = False)
cmds.columnLayout("UI_MainLayout", w = 300, h =500)
cmds.optionMenu("UI_FormatMenu", w = 250, label = "Select a Format")
list01 = ['itemA-01', 'itemB-02', 'itemC-02', 'itemD-01', 'itemE-01', 'itemF-03']
for x in list01:
cmds.menuItem(label = str(x))
cmds.button("UI_SelectButton", label = "OK", w = 200, command=ObjectSelection)
cmds.showWindow("UI_MainWindow") #shows window
def ObjectSelection(*args):
currentFormat = cmds.optionMenu("UI_FormatMenu", query=True, value=True)
print currentFormat
return currentFormat
Use python dictionnaries or class to pass data in your script.
I really don't understand what the problem is.
When you say : "The 'value' is not exactly returning", what do you mean ? Can you tell us what do you get and what do you expect ?
def mainCode():
...
...
showUI()
cmds.optionMenu('filmbackMenu', edit = True, value = xxx ) # <-- I want to grab the value from the menu selection and input into this 'value' flag
...
Here the value selection from the "input value", I guess it is :
cmds.optionMenu('filmbackMenu', edit = True, value = ObjectSelection())
But as there is not filmbackMenu in your code, I'm not sure.
Your second question has been answered on google groups by Justin. You just have to do :
def ObjectSelection(*args):
currentFormat = cmds.optionMenu("UI_FormatMenu", query=True, value=True)
cmds.deleteUI("UI_MainWindow")#close the UI
print currentFormat
return currentFormat
Or maybe "upon a OK button has been selected?" doesn't mean "OK button pressed" ?
If you want to see how use dictionnaries, you can read this other post where I have answered : Maya Python - Using data from UI
You are in a good path to using partial, I recommend you to read about it : Calling back user input values inside maya UI
--- EDIT ---
I tried to create a fully functionnal example :
import maya.cmds as cmds
uiDic = {}
uiDic['this']= 1
def ui_refresh(*args):
uiDic['this'] = cmds.optionMenu("UI_FormatMenu", query=True, value=True)
return uiDic['this']
def showUI():
if cmds.window("UI_MainWindow", exists = True):
cmds.deleteUI("UI_MainWindow")
cmds.window("UI_MainWindow", title = "User Interface Test", w = 500, h = 700, mnb = False, mxb = False, sizeable = False)
cmds.columnLayout("UI_MainLayout", w = 300, h =500)
cmds.optionMenu("UI_FormatMenu", w = 250, label = "Select a Format")
list01 = ['itemA-01', 'itemB-02', 'itemC-02', 'itemD-01', 'itemE-01', 'itemF-03']
for x in list01:
cmds.menuItem(label = str(x))
cmds.button("UI_SelectButton", label = "OK", w = 200, command=ObjectSelection)
uiDic['om_filmback'] = cmds.optionMenu('filmbackMenu' )
list01 = ['itemA-01', 'itemB-02', 'itemC-02', 'itemD-01', 'itemE-01', 'itemF-03']
for x in list01:
cmds.menuItem(label = str(x))
cmds.showWindow("UI_MainWindow") #shows window
def ObjectSelection(*args):
cmds.optionMenu(uiDic['om_filmback'], edit = True, value=ui_refresh())
showUI()
Heading
I made add-on script.
However loading fail in blender UI.
Error message is '_RestrictContext' object has no attribute 'scene' .
But this script is very well run in blender of Text Editor.
Why don't load this add-on?
bl_info = {
"name": "Add Cube",
"author": "jsh",
"version": (1, 0),
"blender": (2, 68, 0),
"location": "View3D > Tool Shelf > Text make",
"description": "Adds a new Mesh Object",
"warning": "",
"wiki_url": "",
"tracker_url": "http://togetherall.infomaster.co.kr",
"category": "Object"}
import bpy
from bpy.props import *
#
# Store properties in the active scene
#
def initSceneProperties(scn):
bpy.types.Scene.MyInt = IntProperty(
name = "Integer",
description = "Enter an integer")
scn['MyInt'] = 17
bpy.types.Scene.MyFloat = FloatProperty(
name = "Float",
description = "Enter a float",
default = 33.33,
min = -100,
max = 100)
bpy.types.Scene.MyBool = BoolProperty(
name = "Boolean",
description = "True or False?")
scn['MyBool'] = True
bpy.types.Scene.MyEnum = EnumProperty(
items = [('Eine', 'Un', 'One'),
('Zwei', 'Deux', 'Two'),
('Drei', 'Trois', 'Three')],
name = "Ziffer")
scn['MyEnum'] = 2
bpy.types.Scene.MyString = StringProperty(
name = "String2")
scn['MyString'] = "Lorem ipsum dolor sit amet"
return
initSceneProperties(bpy.context.scene)
#
# Menu in UI region
#
class UIPanel(bpy.types.Panel):
bl_label = "Make Text"
bl_space_type = "VIEW_3D"
#bl_region_type = "UI"
bl_region_type = "TOOL_PROPS"
def draw(self, context):
layout = self.layout
scn = context.scene
layout.prop(scn, 'MyInt', icon='BLENDER', toggle=True)
layout.prop(scn, 'MyFloat')
layout.prop(scn, 'MyBool')
layout.prop(scn, 'MyEnum')
layout.prop(scn, 'MyString')
layout.operator("idname_must.be_all_lowercase_and_contain_one_dot")
#
# The button prints the values of the properites in the console.
#
class OBJECT_OT_PrintPropsButton(bpy.types.Operator):
bl_idname = "idname_must.be_all_lowercase_and_contain_one_dot"
bl_label = "make"
def execute(self, context):
bpy.ops.mesh.primitive_cube_add()
return{'FINISHED'}
def printProp(label, key, scn):
try:
val = scn[key]
except:
val = 'Undefined'
#print("%s %s" % (key, val))
return val
def register():
bpy.utils.register_class(UIPanel)
bpy.utils.register_class(OBJECT_OT_PrintPropsButton)
def unregister():
bpy.utils.unregister_class(UIPanel)
bpy.utils.unregister_class(OBJECT_OT_PrintPropsButton)
if __name__ == "__main__":
register()
Blender uses a so called RestrictContext during the register / unregsiter phase of a plugin. This means, you're not allowed to do certain operations on the context because the content might not be ready yet.
In your case, you're doing initSceneProperties(bpy.context.scene) in the global module scope, which means it will be executed immediately after that module is being loaded. Move that initialization code for example in your operator's execute() method and do it when the operator is first run, or any other place where it makes sense (as late as possible, as early as necessary).
See the docs on RestrictContext for an example on how to do this.