I am building a program using QTreeWidget. When I double click to a child, it allows to edit this child. I write a function to validate new input value using QDoubleValidator and I want to show a error tooltip but it not work, so I have a question whether I can write a validator that check input value immediately ( like ajax in web development) and show a error tooltip ?
Can anyone have me?
Your question is pretty inspecific because you missed the chance of providing any code.
Anyway, I think you should not need any self implemented QValidator, if and only if the functionality of QDoubleValidator are sufficient.
Thing I would do is implementing a slot in the main widget/dialog whatever and connect the signal void QTreeWidget::itemChanged(QTreeWidgetItem *item, int column) to the created slot. Whenever any tree item changes the slot gets invoked.
Inside the slot you may do any magic for validating the change, wheter you use QDoubleValidator or not. After any invalid check you may display an error message or pop up a QMessageBox.
If you require more information or help you have to provide more information. Feel free to generate a MCVE. For a nice example look here.
Related
I am developing an application to feed a database. My main window is basically a menu that opens forms for different utilities.
Not sure if it's the best practice but let me explain what I'm trying to do:
my class mainwindow has a private QString that will store the current project name. In the menu, "Load" opens the form (another class) that lists all the existing projects in a combobox. The user chooses the project he wants and clicks OK.
I would like to return the combobox.currentText() into the dedicated private variable. After some research I still cannot figure out how to make it, wether I should use SIGNAL from the form to trigger a SLOT of the mainform or if there is a simple way to just return a value after pressing OK (such as an input dialog). If i am not clear enough, maybe the following sketch could help.
I definitively have a lack of knowledge on the subject but would be grateful for some help.
Indeed if your form for loading a project would emit a signal currentProjectChanged as soon as the user accepts the form (presses the OK button), this signal could be connected to a slot of the main window. For simple things this may be fine and elegant.
On the other hand reacting on actions sometimes needs more logic. If your action triggers a slot that cares for action execution, this slot probably should implement the logic. It should open the form and check whether the user has accepted the project change (pressed OK). In this case the action execution slot could get the new project name from the form and call a main window method to pass the new project name.
I'm using a wxToolBar which makes use of a drop-down menu with following code (simplified):
g_toolBar1->AddTool(TOOLBAR_CMD_CONTROL_DROPDOWN,_("Control elements"),MainWin::getBitmap(gearsXPM,"gears"),wxNullBitmap,wxITEM_DROPDOWN);
custParent->Connect(TOOLBAR_CMD_CONTROL_DROPDOWN,wxEVT_COMMAND_TOOL_CLICKED,wxCommandEventHandler(DrawCanvasSwitcher::OnToolbar),NULL,g_drawCanvas);
wxMenu *controlMenu=new wxMenu;
// following is repeated several times to have more than onw drop-down item
// (*it) is an iterator to an container holding the required data
wxMenuItem *item=new wxMenuItem(controlMenu,wxID_ANY,(*it)->m_entityParams.m_name,(*it)->m_entityParams.m_shorthelp);
controlMenu->Append(item);
item->SetBitmap(*(*it)->m_entityParams.m_bmToolbar);
item->SetId((*it)->m_wxID);
custParent->Connect(item->GetId(),wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED,wxCommandEventHandler(DrawCanvasSwitcher::OnMenu),NULL,g_drawCanvas);
g_toolBar1->SetDropdownMenu(TOOLBAR_CMD_CONTROL_DROPDOWN,controlMenu);
g_toolBar1->Realize();
So the first Connect() is successful and when clicking the top toolbar item, I end up in DrawCanvasSwitcher::OnToolbar(). The second Connect() - which is simply copied from a different position in same file and where it works fine for normal menu items - does not work, I never get an event in DrawCanvasSwitcher::OnMenu() when selecting a toolbar drop-down item. The event type is the same as used in the toolbar-sample that comes with wxWidgets 3.1. g_drawCancas and custParent all are valid (and work for plain menu items).
So what could be the reason why I do not reveice events on clicked drop-down items?
Edit: using wxEVT_COMMAND_MENU_SELECTED instead of wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED does not make any difference, still no event...
I don't see anything obviously wrong in the code, so, as always, the best thing to do would be to try to simplify it as much as possible and/or try doing the same thing in the toolbar sample to see if you can reproduce the problem there.
One thing I'd try would be to specify (*it)->m_wxID immediately when creating the menu item, instead of setting it later. It should work as written, of course, but it's rather uncommon to do it like this, so perhaps there is a bug somewhere there.
If you do manage to reproduce the problem in the toolbar sample (e.g. just remove the event table entry for MyFrame::OnToolDropdown() there and use Connect() instead), please do report it as a bug, mentioning your platform.
And, finally, although it's completely unrelated to your problem, there is really no reason whatsoever to use Connect() instead of Bind() with wxWidgets 3.x, you should really switch to the latter for better compile-time safety and flexibility.
I have a QPlainTextEdit widget in my application which has a QSyntaxHighlighter assigned to it. Upon each content change within that text edit area, I need to get a notification (to update the global application save/changed state). However, the signal textChanged() also gets emitted each time the highlighter gets to work, which I need to filter out somehow.
I already had a look at modificationChanged(), but that doesn't seem to work either. It ignores the highlighting changes and successfully notifies me upon the first content change, but not of any subsequent changes. The documentation mentions, that I should be able to reset the internal state with setModified(false) but that method doesn't seem to exist.
Any ideas on how to filter the changes?
Do I have to switch to QTextDocument which seems to have a single contentsChanged() that is said to ignore syntax highlighting changes?
It turns out I already was on the right track...just not all the way:
I indeed need to listen to modificationChanged signals since they are emitted on content changes (which are the relevant events for my application save state handling).
I however originally did not see a way to reset the internal modification state (e.g. when my application saves its state). The reason was that setModified(bool) does not exist for the QPlainTextEdit, but I realized that each of those objects has a QTextDocument internally which does have that method. So I simply call that each time I need to reset the state to non-modified:
m_pPlainTextEdit->document()->setModified(false);
As a result, when the content is changed the next time, modificationChanged will get emitted again so that I can react to it and for example enable the "Save" icon.
BTW: The signal contentsChanged from QTextDocument is also emitted upon formatting changes, so not helpful in my scenario.
I have not tested it, it is just basically an idea.
When the user modifies the text, it is a QKeyEvent.
When the highlighter does, it is some sort of QInputMethodEvent (?)
What you could do is, check if the event is a QKeyEvent, and if it is not, block it.
You can create a filterobject class, or just define the following method in the class that contains the QTextEdit.
bool MyClass::eventFilter(QObject *o, QEvent *e)
{
if (e->type() == QKeyEvent) //The user modified the text edit
return false;
else
return true;
}
And you have to install it (for example in the constructor), if you defined it in the class that contains QTextEdit:
myTextEdit->installEventFilter(this);
Instead of hooking into modificationChanged(), and resetting the modified flag everytime, you could just hook into textChanged(). It's triggered anytime you make a change to the document, regardless if had been previously changed or not...
We are implementing a text field to do numeric entry. We subclass the standard wxTextCtrl. Behavior is that when user decides to edit the value they get a full precision version and it is selected.
First attempt was to override the focus handler so that when the field gets focus the value is shown in full and selected. This works great except for the cases when you click on the field. In that case, the focus handler is called and the value is selected...but some time after that it is deselected and the edit point put where the mouse click occurred. I thought maybe I could override SetSelection and set a debug point but it seems to use some other method to set the selection! I'm stuck having to walk through the miles of event handling crap to figure it out...I'm thinking in the mouse button handlers but so far I haven't found any.
It would be nice if someone who might already know what I need to override to point it out. Where do I need to be looking?
I would try this code for your wxTextCtrl (but I'm not sure if this is what you want - focus and click)
m_textCtrl1->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( MyDialog1::LeftDown ), NULL, this );
m_textCtrl1->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( MyDialog1::SetFocus ), NULL, this );
void LeftDown( wxMouseEvent& event );
void SetFocus( wxFocusEvent& event );
In case what you do is overwritten by the default (system) handler of your control you could try 'wxPostEvent' to do what you want later (after the default handling).
I also suggest using a designer for this (for this question I stole some code generated by wxFormBuilder)
Answer is that it can't be done. The behavior I'm trying to override is implemented by the win32 component itself and wx doesn't provide any method to doing so....short of bypassing WX to get the win32 handle and using win32 api.
Would need to write a new component in the WX api to get the desired behavior.
In win32, how do I setup a callback mechanism for RichEdit I have not created myself?
PART 1
I'm reading from a textedit field in another application's GUI. This works just fine now, except after the first read I'd like to fetch only new or modified lines. In GTK+ or Qt I'd just install a callback on some signal the field edits when its changed, but how does it work on Win32?
My MSDN searches result with nothing useful, probably because I don't know the exact term to search for. The class of the textedit is RichText20W, and it has some messages that are probably used somehow, though that article just discusses using them for the parent of the class.
PART 2
Also, if there is no such "text changed, here is the newly inserted text" callback which returns the new content immediately, I need some way to easily detect what is new. From top-of-my-head:
Have a marker at the end of the text block we've read, and only read between that and the end.
Store what we've read previously, and after a second read, remove the duplicate part from the latter to have the newly inserted stuff.
Option 2 might not be viable, since the textedit can contain any amount of text. The marker part sounds doable, but yet again, my feeble Win32 skills and horrible Win32 function names prevent me from finding the right way to do it.
Note that all these must be doable for a textedit I do not own and have not created, they belong to a third party process.
Code samples in C++ highly appreciated.
Disclaimer
Obviously, if there is some better way of doing it, let me know. I only assumed callback would be the way to go based on my previous experience with GTK+/Qt. Feel free to show me the path :)
Win32 controls don't work on message-specific callbacks that you can subscribe to. They just send messages to their parent window when something happens, in this case EN_UPDATE, EN_CHANGE and all that. Even these events don't tell you what text changed. They only tell you that it did change.
You could subclass the parent, but the documentation for SetWindowLongPtr explicitly says you "should not subclass a window class created by another process." Something like this is probably possible with hooks, but I haven't used them enough to say for certain how you'd actually do it.
I realize it's an old post, but this article seems to be doing something similar.
Based on Joel's answer, I quit looking for callbacks and just made a small class that hooks itself (not by a real API hook though) to the richedit and polls it once a second for content length, and if it has changed since the last poll, it asks for the content, compares that to previous known content and emits a signal with the changed content.
This seems to work OK for this purpose, but if someone knows a better way still (some real and tested way of doing it via API hooks or something), please post.