I want to create a function which takes the Caption of a pressed button and put it into an Edit field. I have multiple buttons, and I don't want to have multiple OnClick events with almost the same code in each of them.
I've searched and tried out stuff for hours, but can't seem to find anything like that (but I think I am not the only one with this problem).
I am not really new to programming but neither am I good at it.
Edit: I remember that there is a parameter in the click functions in .NET which is EventArgs e, which is missing while working with Embarcadero.
private void button_Click(object sender, EventArgs e)
{
edit.Text = e.Caption; //I don't really remember the exact syntax but I hope you get what I meant
}
Most VCL/FMX event handlers have a Sender parameter, which is a pointer to the object that is firing the event. For example:
void __fastcall TMyForm::ButtonClick(TObject *Sender)
{
Edit1->Text = static_cast<TButton*>(Sender)->Caption;
}
Just assign this single event handler to the OnClick event of all of your TButton objects. The Sender will be the current button being pressed.
Note to the above answer by Remy - for VCL the property name is "Caption" but for FMX the property name for a button is "Text"
Related
I am very new to ZK framework and trying to customize few things and have struck at one point which I am not sure how to achieve that.
I have a predefined section where I need to show 2 drop down and a button and need to persist those drop down values on button click event.
This is how It has been define in Spring file
<bean id="mybean" parent="parentBean" class="WidgetRenderer">
<property name="detailRenderer">
<bean class="DetailsListRenderer" parent="abstractWidgetDetailRenderer"/>
</property>
</bean>
Here mybean is being used to show main section and I am adding my drop down using this bean while button are being added to detailRenderer.
Save button is bind to onClick event, but I am not sure how I can fetch values from my custom drop down?
I am aware about binding those Dropdown with onClick event but they have to be in same class.
Can any one suggest me how I can fetch values of those drop down.I am creating down down with following code
Listbox listbox = new Listbox();
listbox.appendItem("item1", "item1");
listbox.appendItem("item2", "item2");
This is my button code in another class
protected void createUpdateStatusButton(Widget widget,Div container)
{
Button button = new Button(LabelUtils.getLabel(widget, buttonLabelName, new Object[0]));
button.setParent(container);
button.addEventListener("onClick", new EventListener()
{
public void onEvent(Event event)throws Exception
{
MyClass.this.handleSaveStatusEvent(widget, event);
}
});
}
You may want to listen to the onSelect (I prefer to use Events.ON_SELECT rather than writing the strings) which is more specific to when the Listbox selection changes.
Either way, the key is to get the information you want from the Event passed to your EventListener, rather than going back to your Listbox itself. The basic Event usually carries useful information on getTarget and getData but using more specific events (SelectEvent in this case) will give you access to more relevant info.
button.addEventListener(Events.ON_SELECT, new EventListener<SelectEvent<Listitem, MyDataObject>() {
public void onEvent(SelectEvent<Listitem, MyDataObject> event) {
// Now you can access the details of the selection event..
List<Listitem> selectedItems = event.getSelectedItems();
List<MyDataObject> selectedObjects = event.getSelectedObjects();
}
});
You can find out what events are available for different ZK widgets in their Component Reference documentation.
If I understand the question (I don't think I did in my previous response) you want to gather information from the page (eg: Listbox selection state) when the user clicks a button. Your problem being that you are using disparate classes to compose the page and so don't have access to the various ZK Components when the button is clicked.
(Ignoring the multiple class issue for a minute)
From a high level, there are sort of two camps in the ZK community. The newer MVVM approach suggests the view should push the relevant state to the back end as the user interacts with the front end. This way, the back end never needs to ask for the client state, and when the button is clicked, the values/state are on the server ready to be used.
The other camp binds the client to the server such that the back end always has access to the client Components and when the button is clicked, the values/state can easily be retrieved by interacting with the components.
Another approach is more like what I was talking about in my previous answer, to not bind the back end to the client at all but to rely on event data as much as possible. I favor this approach where it is sufficient.
Now, you're free to choose your favored approach and ZK has lots of documentation on how to work in either of these camps. The question then is where is the client state stored on the server (either pushed there by the client in MVVM or bound there in MVC). I don't think that's a question that can be solved here, that's a software engineering challenge. I personally suggest you take on standard ZK patterns so as not to but heads with the framework. If you really want to go your route, you can grab a reference to the Listbox on the fly like so:
public class Foo {
public static final String LISTBOX_ID = "myListbox";
public void renderListbox(Component parent, MyItem items) {
Listbox listbox = new Listbox();
listbox.setId(LISTBOX_ID);
listbox.setParent(parent);
for (MyItem item : items) {
listbox.appendItem(item.getName(), item);
}
}
}
public class Bar {
#Listen(Events.ON_CLICK + " = #saveButton")
public void saveButtonClicked(Event event) {
Component saveButton = event.getTarget();
Listbox listbox = (Listbox) saveButton.getFellow(Foo.LISTBOX_ID);
Set<Listitem> selection = listbox.getSelectedItems();
// do something
}
Following the JavaFX Tutorial here: http://docs.oracle.com/javafx/2/get_started/fxml_tutorial.htm, trying to make it run in Clojure. For now I'm just doing lein run after setting up :aot :all and stuff with (:gen-class) etc. It took a few days of figuring out, but now it seems to be mostly working.
In src/jfxtwo/ClojureExampleController.clj:
(defn -handleSubmitButtonAction [^ActionEvent event]
(let [actiontarget (Text.)]
(println "event button pressed")
(println "Event instance:" event)
(println "Event class:" (class event))
(.setText actiontarget "Sign in button pressed...")))
In resources/fxml_example.fxml:
<GridPane fx:controller= "jfxtwo.ClojureExampleController"
xmlns:fx= "http://javafx.com/fxml"
alignment= "center" hgap= "10" vgap= "10"
styleClass= "root" >
...
<Button text= "Sign In"
onAction= "#handleSubmitButtonAction" />
...
<Text fx:id= "actiontarget"
GridPane.columnIndex= "1" GridPane.rowIndex= "6" />
...
I have my clojure code able to read the fxml and css file to generate the proper GUI. When I press the button I can see the event handler being called, but I don't know how to access the Text I want to change, or the ActionEvent instance that is associated with the button press. I tried (println event) and (println (class event)) expecting to see something about an ActionEvent instance, but this only results in showing me that for whatever reason the callback function thinks the event is a ClojureExampleController, even though the type hint says it should be an ActionEvent:
event button pressed
Event instance: #<ClojureExampleController jfxtwo.ClojureExampleController#3e61061d>
Event class: jfxtwo.ClojureExampleController
The Java code to do this looks like this:
public class JFXAppSampleController {
#FXML private Text actiontarget;
#FXML protected void handleSubmitButtonAction(ActionEvent event) {
actiontarget.setText("Sign in button pressed");
}
}
Clearle the #FXML annotation is doing the magic here. What's going on, and how do I make this work in Clojure?
Also, is there a way to bind the button press to the text change directly in the FXML so I don't really have to handle a gui->gui change in the code-behind, and instead only deal with the logic associated with the button press? I'm guessing yes, but I haven't gotten to that point in the tutorial.
thanks!
You need an explicit this argument in your handler:
(defn -handleSubmitButtonAction [this ^ActionEvent event]
...)
Perhaps a more accurate way of putting this is that event is the this argument in your handler as exhibited in the question text and you need to add a second argument to accept the event in and move the type hint to it (and probably rename the first argument to this for readability).
Given the fact that your code gets called at all, it would seem that JavaFX is happy to call a handler without passing it the event at all if it doesn't care about it (as evidenced by not having a formal parameter corresponding to it).
The type hint's only purpose is to allow the Clojure compiler to avoid emitting reflective code when ActionEvent methods are called on event. This will not prevent passing an object of a different type to the function.
For some reason, the AlwaysOnTop attribute for a form's design isn't properly working.
Here's the context: we are trying to have a form that stays on top of every other one when opened. Simple no? Also, we don't want to set the WindowType to Popup according to my superior for some other reason (if you have any idea why, please let me know).
So my question is, is there any parameter/security feature somewhere that somehow restricts the forms to be on top at any time?
Even WinApi's setForegroundWindow returns false with the form's hWnd. Any ideas?
Oh, also we're running on Dynamics AX 4.0.
If you want your form to have modal behavior, then call the wait method from the form itself!
public void run()
{
super();
this.wait(true);
}
The true parameter triggers the modal mode. This works on all versions of AX.
The wait may be called from the caller instead, but that is less attractive as most forms are called through menu items.
formRun.init();
formRun.run();
formRun.wait(true);
I managed this case long time ago with the lostFocus event and the setFocus method. I didn't find a proper way to make a form stay on top (I think AX prevents this specifically to avoid locking a terminal) but it worked fine this way: When the form lost focus, set the focus on the form.
I don't have the code as it was on an old project. It was for a PDA project but I think you can't ever avoid user on changing form with Alt+Tab.
This is an interesting point, please keep us updated.
EDIT:
Someome in twitter got an cute solution for modal forms. I'm pretty sure it will make the trick for you. In the init method of the form:
public void run()
{
super();
element.wait(true);
// Execution will resume at this point, only after
// the user has closed the form.
}
Source: http://gotdax.blogspot.com.es/2013/08/modal-forms-in-dynamics-ax.html
What I did to solve this was by making the form modal through WinAPI. The code below is a copy from a saved text so it might need some polishing. (Also keep in mind that it might not be working as of AX2009.)
void setFormModal(int _thisHWND, boolean _bModal)
{
DLL _winApiDLL;
DLLFunction _EnabledWindow;
DLLFunction _getTop;
DLLFunction _getNext;
DLLFunction _getParent;
void local_enableWHND(int _lHWND)
{
int lnextWnd;
lnextWnd = _getTop.call(_getParent.call(_lHWND));
while (lnextWnd)
{
if (lnextWnd != _lHWND)
_enabledWindow.call(lnextWnd, (!_bModal));
lnextWnd = _getNext.call(lnextWnd, 2);
}
}
;
_winApiDLL = new DLL('user32');
_getNext = new DLLFunction(_winApiDLL, "GetWindow");
_EnabledWindow = new DLLFunction(_winApiDLL, "EnableWindow");
_getTop = new DLLFunction(_winApiDLL, "GetTopWindow");
_getParent = new DLLFunction(_winApiDLL, "GetParent");
_getParent.returns(ExtTypes:: DWORD);
_getParent.arg(ExtTypes:: DWORD);
_EnabledWindow.returns(ExtTypes:: DWORD);
_EnabledWindow.arg(ExtTypes:: DWORD, ExtTypes:: DWORD);
_getTop.returns(ExtTypes:: DWORD);
_getTop.arg(ExtTypes:: DWORD);
_getNext.returns(ExtTypes:: DWORD);
_getNext.arg(ExtTypes:: DWORD, ExtTypes:: DWORD);
local_enableWHND(_thisHWND);
local_enableWHND(_getParent.call(_thisHWND));
}
I'm trying to attach an event handler to the keyDown event in a canvas element. Here is a simplified version of my code.
class CanvasFun{
CanvasElement canvas;
CanvasFun(this.canvas){
print("Game is loading!");
this.canvas.onKeyDown.listen(handleInput);
}
void handleInput(e)
{
//breakpoint is never hit
print(e.keyCode);
}
}
I've removed some of the drawing code. In my main function I simply query the canvas element and pass it to my CanvasFun constructor.
I've also tried doing it this way:
void main() {
var canvas = query("#Game");
canvas.onKeyDown.listen(handleInput);
var canvasFun = new CanvasFun(canvas);
}
void handleInput(e)
{
print(e.keyCode);
}
The reason why the event is not firing is because the focus is on the document (or some other element like an input, for example). And in fact, canvas element even when focused does not fire an event. Some elements do, like input elements.
The solution is to listen to key down events from the document or window:
window.onKeyDown.listen(handleInput);
document.onKeyDown.listen(handleInput); // You already noticed this worked.
John McCutchan has written a nice Dart package to help handle keyboard input. You can read more about it here: http://dartgamedevs.org/blog/2012/12/11/keyboard-input/
Note that this library helps you handle input "correctly". You do not want to do any "work" in the input handling, instead you simply want to register that a key was pressed. You can check the state of any key presses inside of your requestAnimationFrame callback.
Hope that helps!
There exists a workaround to get the canvas-element accept KeyboardEvents:
Problems handling KeyboardEvents on DartFlash
Once you add the tabindex-attribute to your canvas-element, it can get the focus and then it will receive KeyboardEvents.
It looks like I can get it to work if I register the event on the document rather than the canvas element.
document.onKeyDown.listen(handleInput);
I've got a shell tray icon with an attached context menu. The problem I'm having is that calling ShowDialog() from a context menu Clicked handler does not result in a modal dialog.
It's easy to reproduce this with a default C# project. Simply add the following code to the Form1.cs file:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
ToolStripMenuItem contextMenuShowMsg = new System.Windows.Forms.ToolStripMenuItem();
contextMenuShowMsg.Name = "contextMenuShowMsg";
contextMenuShowMsg.Text = "Show MessageBox...";
contextMenuShowMsg.Click += new System.EventHandler(this.contextMenuShowMsg_Click);
ContextMenuStrip contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
contextMenuStrip.Items.Add(contextMenuShowMsg);
NotifyIcon notifyIcon = new NotifyIcon();
notifyIcon.Text = "DlgTest";
notifyIcon.Icon = SystemIcons.Application;
notifyIcon.Visible = true;
notifyIcon.ContextMenuStrip = contextMenuStrip;
}
private void contextMenuShowMsg_Click(object sender, EventArgs e)
{
MessageBox.Show(this, "Test MessageBox");
}
If you build and run this, you will be able to get two message boxes on the screen by simply choosing the context menu item twice. Shouldn't this be modal? Replacing this with a call to ShowDialog() for another form results in the same non-modal behavior.
My best guess is that the NotifyIcon isn't specifically tied to the Form, as it would be in a typical Windows application. But I don't see any way of doing that.
Any ideas? Thanks in advance for any help!
I would suggest doing two things before you attempt to display a modal message box:
Make your icon's owner-window visible.
Give it focus.
Once you've done that, the this in the MessageBox.Show becomes a legal "modality parent".
Heck, it even makes more sense that the message box will be displayed on top of whatever program generated it, right? That way, the user has some context for what the message box is about!
You will need to keep track of activations of your system tray menu, and disable it when a dialog is open.