Dropdown menu button in tcl/tk - user-interface

Is there any way to create a drop down toolbar button(Like Paste button in MS Word) using Tcl/TK?.I have googled a lot but nothing found.Any help will be appreciable.

You probably want to use a menubutton and a menu, probably with radiobutton entries if I've understood which UI element in Word you're talking about. (Or maybe a ttk::menubutton and menu.) Now, if you're doing something very simple with it then you can make do with just tk_optionMenu as a way to combine those commands, but that's just a simple procedure; if you're doing something complicated with the menu, it's probably easier to write it yourself or at least to get the code for tk_optionMenu and to customise it how you want it to work.
The source code for tk_optionMenu isn't very long; I'll paste the non-comment parts of it here:
proc ::tk_optionMenu {w varName firstValue args} {
upvar #0 $varName var
if {![info exists var]} {
set var $firstValue
}
menubutton $w -textvariable $varName -indicatoron 1 -menu $w.menu \
-relief raised -highlightthickness 1 -anchor c \
-direction flush
menu $w.menu -tearoff 0
$w.menu add radiobutton -label $firstValue -variable $varName
foreach i $args {
$w.menu add radiobutton -label $i -variable $varName
}
return $w.menu
}
You probably want to pay attention to how the menubutton and menu are connected to each other. ttk::menubutton is mostly a drop-in replacement for menubutton, except for different look-and-feel configuration options.

Related

MEL Querying a selected button

I am new to using MEL to write scripts.
I have two radio buttons, one and two. When radio button 'two' is selected, I want the script to select the two cube objects I have created in my scene (cube1 and cube2), so that when I use my 'rotate' button (a regular push button), both of the cubes rotate.
On the other hand, if the radio button 'one' is selected, then only one of them (cube1) should rotate when I press the rotate button.
I have my radio buttons as follows:
$radio1 = `radioCollection`;
//my radio buttons
$one = `radioButton -label "1 cube"`;
$two = `radioButton -label "2 cubes"`;
radioCollection -edit -select $one $radio1; //so that this one is selected by default
and for the rotate button I have this that rotates the cube object 'cube1' by 30 degrees. This is currently NOT linked to my radio buttons.
button -label "rotate" -command "setAttr cube1.rotateZ `floatSliderGrp -q -value 30.0`";
Thoughts? Should I query the radio button's state? This would be so much easier for me in another language! I could see myself saying something like "if $radiotwo.pressed, then cube1.rotateZ && cube2.rotateZ"
All Maya UI items are completely imperative: you have to issue commands and get results, there is no 'state': the 'button' or whatever will just be the string name of the object you'll use for issuing the commands
To get the state of the radiocollection you call radioCollection -q -select on the collection, which will return the name of the selected radio button; you'd use that to drive your logic.
string $w = `window`;
string $c = `columnLayout`;
string $radiocol = `radioCollection "radio buttons"`;
string $one_cube = `radioButton -label "1 cube"`;
string $two_cube = `radioButton -label "2 cubes"`;
radioCollection -edit -select $one_cube $radiocol;
showWindow $w;
global proc string get_radio_state(string $radio)
{
string $selected = `radioCollection -q -select $radio`;
return `radioButton -q -label $selected`;
}
print `get_radio_state($radiocol)`;
fiddle with the radio buttons and get_radio_state($radiocol); it should return the name of the selected button.
If you're already familiar with other languages, you should probably skip MEL and jump straight to maya python: it's much more capable and less tweaky. Lots of discussion here and here
For comparison, here's a python version of the same idea:
w = cmds.window()
c =cmds.columnLayout()
rc = cmds.radioCollection()
cmds.radioButton('one', label="1 cube")
cmds.radioButton('two', label = "2 cubes")
def print_selected(*ignore):
print "selected", cmds.radioCollection(rc, q=True, select=True)
btn = cmds.button("print selected", command=print_selected)
cmds.showWindow(w)
Here the button does the same thing as the print statement in the earlier example

SketchUp API: How to add a check box to a menu item

I don't see it anywhere in the Ruby API documentation but just in case I'm missing something...
I'm writing a plugin for SketchUp and I'm trying to add some options to the menu bar. One of my options would work best as a checkbox, but right now I have to have two separate buttons. Is there a way to create a checkbox menu item with the Ruby API?
Here's what I had to do instead:
foo = true
UI.menu("Plugins").add_item("Turn foo_option on") { #foo = true }
UI.menu("Plugins").add_item("Turn foo_option off") { #foo = false }
...and then I just use foo to change the options. Is there a cleaner way to do this?
SketchUp can have check marks in menu items. Both menu items and commands can have a validation proc. The documentation for set_validation_proc gives this example:
plugins_menu = UI.menu("Plugins")
item = plugins_menu.add_item("Test") { UI.messagebox "My Test Item"}
status = plugins_menu.set_validation_proc(item) {
if Sketchup.is_pro?
MF_ENABLED
else
MF_GRAYED
end
}
Although for checkmarks you would use the constants MF_CHECKED and MF_UNCHECKED
http://www.sketchup.com/intl/en/developer/docs/ourdoc/menu#set_validation_proc
http://www.sketchup.com/intl/en/developer/docs/ourdoc/command#set_validation_proc
I have not seen a checkbox menu item created from an extensions before, but I'm a beginning user so that's maybe why.
An other approach would be to do it like this:
unless file_loaded?(__FILE__)
plugin_menu = UI.menu("Plugin")
option_menu = plugin_menu.add_submenu("NameOfOption")
option_menu.add_item("OptionA"){ }
option_menu.add_item("OptionB"){ }
file_loaded(__FILE__)
end
The file_loaded?(_ FILE _) makes sure the menu only is created once, instead of every time you load your script. I hope this is helpfull. Maybe some experts now a way to create a checkbox menu.

Create new window in tcl/tk

How can i create a same gui every time by clicking the button without closing current one?
wm title . "abcd"
wm geometry . 50x50
pack [button .b -text "new"]
Please help me.
The toplevel command creates a new window for you to put widgets in. It's a good idea to use a procedure for building the overall GUI in that window:
wm title . "abcd"
wm geometry . 50x50
pack [button .b -text "new" -command makeWindow]
set counter 0
proc makeWindow {} {
# Make a unique widget name
global counter
set w .gui[incr counter]
# Make the toplevel
toplevel $w
wm title $w "This is $w"
# Put a GUI in it
pack [label $w.xmpl -text "This is an example"]
pack [button $w.ok -text OK -command [list destroy $w]]
}
Each of these windows that you make is as independent or dependent on the others as you want. It depends on how you write the code, arrange the variables, design the callbacks, etc.

How to implement tk scrollbar for multiple listboxes (TCL)?

I tried all sort of options but no success in implement simple scrollbar for two or more listboxes. Following is my code giving error while scrolling. I hope you guys are helping me...
scrollbar .scroll -orient v
pack .scroll -side left -fill y
listbox .lis1
pack .lis1 -side left
listbox .lis2
pack .lis2 -side left
for {set x 0} {$x < 100} {incr x} {
.lis1 insert end $x
.lis2 insert end $x
}
.lis1 configure -yscrollcommand [list .scroll set]
.lis2 configure -yscrollcommand [list .scroll set]
.scroll configure -command ".lis1 yview .lis2 yview ";
thanking you.
There are a number of examples on the Tcler's wiki, but the core principle is to use a procedure to ensure that the scrolling protocol is synchronized between the widgets. Here's an example based off that wiki page:
# Some data to scroll through
set ::items [lrepeat 10 {*}"The quick brown fox jumps over the lazy dog."]
# Some widgets that will scroll together
listbox .list1 -listvar ::items -yscrollcommand {setScroll .scroll}
listbox .list2 -listvar ::items -yscrollcommand {setScroll .scroll}
scrollbar .scroll -orient vertical -command {synchScroll {.list1 .list2} yview}
# The connectors
proc setScroll {s args} {
$s set {*}$args
{*}[$s cget -command] moveto [lindex [$s get] 0]
}
proc synchScroll {widgets args} {
foreach w $widgets {$w {*}$args}
}
# Put the GUI together
pack .list1 .scroll .list2 -side left -fill y
It's worth noting that you can also plug any other scrollable widget into this scheme; everything in Tk scrolls the same way (except with -xscrollcommand and xview for horizontal scrolling, together with a change of scrollbar orientation). Furthermore, the connectors here, unlike the ones on the wiki page, can be used with multiple groups of scrolled widgets at once; the knowledge of what is scrolled together is stored in the -command option of the scrollbar (first argument to synchScroll callback).
[EDIT]: For 8.4 and before, you need slightly different connector procedures:
# The connectors
proc setScroll {s args} {
eval [list $s set] $args
eval [$s cget -command] [list moveto [lindex [$s get] 0]]
}
proc synchScroll {widgets args} {
foreach w $widgets {eval [list $w] $args}
}
Everything else will be the same.
I know that this post is really old but I recently discovered what I think is a fairly simple solution. Instead of using the vertical scrollbar I found that I can use the slider widget. With the slider you can get the position of the slider and use that to set the yview of the listbox(es). Multiple listboxes can be scrolled simultaneously. I use vtcl to build the GUI so the code I can provide may not beimmediately obvious for those using tk wm comands. But here is the code I use. It is bound to slider motion.
set listIndex [$widget(Scale1) get]
$widget(Listbox1) yview $listIndex
$widget(Listbox2) yview $listIndex
Hope that is helpful to somebody.
If you plan to do much work in the the callback command - make a procedure to do it as that is both faster (the procedure gets byte compiled) and less likely to introduce tcl syntax problems. In this case you are trying to perform two tcl commands in the scrollbar function so you need to separate the statements using newline or a semicolon.
Calling the scrollbar set function from both listboxes will just have the second one override the first. You either need a function to merge those two or if the lists have the same lengths, just call it from one of them to set the scrollbar size and position and then update all listboxes with the scrollbar callback.
There is a multilistbox package somewhere - try the Tcl wiki to locate examples.

Insert progressbar into statusbar panel using powershell and windows forms

I am currently working on a project that requires me to put a progressbar in one of the panels of a statusbar. Does anyone have any experience with this, or can anyone provide any input or direction on how it is done. I have been searching for 2 days now for a solution with no luck. There is still not an abundance of powershell help out there, especially when it comes to windows forms.
This is relatively simple to do with PowerShell data sources in WPK.
You can get WPK as part of the PowerShellPack.
Here's a pretty decent progress viewer written in WPK:
New-Grid -Columns 2 {
New-TextBlock -Margin 10 -TextWrapping Wrap -ZIndex 1 -HorizontalAlignment Left -FontWeight Bold -FontSize 12 -DataBinding #{
"Text" = "LastProgress.Activity"
}
New-TextBlock -Margin 10 -ZIndex 1 -TextWrapping Wrap -Column 1 -VerticalAlignment Bottom -HorizontalAlignment Right -FontStyle Italic -FontSize 12 -DataBinding #{
"Text" = "LastProgress.StatusDescription"
}
New-ProgressBar -ColumnSpan 2 -MinHeight 250 -Name ProgressPercent -DataBinding #{
"Value" = "LastProgress.PercentComplete"
}
} -DataContext {
Get-PowerShellDataSource -Script {
foreach ($n in 1..100) {
Write-Progress "MajorProgress" "MinorProgress" -PercentComplete $n
Start-Sleep -Milliseconds 250
}
}
} -AsJob
The PowerShellDataSource returns an object with a list of all of the outputs for a given stream and the last item outputted on the given stream (i.e. Progress and LastProgress). In order to display the progress bar, we need bind to the LastProgress property.
The first half of the code declares the progress bar. By using the -DataBinding parameter the TextBlocks and Progress bars will automatically sync to the data context. Data context can either be declared at this level (as is shown in the example) or can be in a parent control.
The DataContext in this example is a simple PowerShell script that uses Write-Progress to output a test message every quarter second, but you can use any script you'd like.
Hope this helps.

Resources