Is there a way to find a GTKWidget by a control name / or id, from within the current window scope from a c/c++?
In Winforms, you had something like this:
public class Form1 : Form
{
public void Test()
{
this.Controls.Find("ControlName");
}
}
You can set names on widgets, using gtk_widget_set_name(), but I don't think there are built-in functions to find widgets in hierarchies based on the name.
That wouldn't be too hard to write if you had a need, though.
As Micah pointed out, it's not how GTK+ applications are generally structured, it's way more common to keep pointers to needed widgets from the time they were created, for manually built UI:s.
In GTK+ we store references to any widget we may need to access in later code using a variable (or struct/class/etc.) that is passed around as user data in the relevant callback functions. If you are using a UI builder (such as glade) then yes, there would be a way to reference the widget by the name you gave it in the UI builder. Otherwise, the answer is that there is not a way to "find" the widgets quite like that.
If you could provide a more specific example I could elaborate.
Related
I'm using a QJSEngine to make an application scriptable. I'd like the JavaScript side to be able to modify the user interface. My main issue right now is accessing the Qt API from JavaScript.
To create widgets, I added a createWidget() wrapper that uses QUILoader:
// JavaScript
var w = helpers.createWidget("QPushButton");
// C++
QJSValue helpers::createWidget(QString type)
{
QUILoader ld;
return engine.newQObject(ld.createWidget(type));
}
I've also registered all the enums from qt_getQtMetaObject(), which seems to take care of all the namespace-level enums from qnamespace.h. It doesn't look like it's part of the public API though.
Am I really supposed to this stuff manually or am I missing something? Isn't there a registerAllTheThings() function that creates a global Qt object through which the Qt API available?
If there isn't, then I have a problem. I can create QWidgets with a QUILoader, but I couldn't find a way of creating other objects, such as a QStandardItemModel. I thought all Qt classes would already be registered through qRegisterMetaType(), but they're not: QMetaType::type("QStandardItemModel") fails by returning UnknownType. Again, am I missing some initialization function call that registers everything?
I would recommend using a QQmlEngine instead of the QJSEngine.
Is is derived from QJSEngine so it can do the same things, in the same module so no extra dependencies.
It provides an easy way to register types for instantiation in QML, has a plugin loading mechanism (imports), etc.
I presented that as part of my talk at Qt World Summit 2015: https://www.youtube.com/watch?v=7LsKoVrb8C8
Typical situation: you have an application, that save and load preferences
(save and load handled by class Config).
Imagine there's such a preference for fonts of some GUI elements.
So we have
struct Font;
struct Config {
const Font& getFontForSpecificGUIElement() const;
//save to disk if Font changed
void setFontForSpecificGUIElement(Font);
};
Whenever the font is changed I need to inform all instances of class SpecificGUIElement of that change.
How can achieve such notification functionality?
To keep Config simple I want to decouple that functionality. Besides, there will many properties like this (30-50 of them).
So in general I want:
Not require implementing virtual interfaces
I don't need thread safety
Convenient registration of event handlers
I need notification for new subscribed receivers, with last recent
notification if were any (I mean, as in my example Font changed, and when new GUI elements subscribe on such event, they receive, event automatically triggered for them, and they receive last variant of Font)
Convenient registration of event type (I mean in item above
we create some kind of value cache, so it should be simple add new one)
I suppose this is common enough requirements, so may be there already solution,
in popular C++ libraries, like boost ?
Update:
Why Qt not suitable for me. I see two approaches
with Qt, QEvent subsystem. But because of it is impossible
send event to unknown listeners it is no go. Why not signal/slots, first you need inherit QObject, second to implement (4), I have to create MessageBus class to cache last values, and adding new events starts require to much work:
add data field, add new signal, add function(X) to emit new signal, because of signal actually protected functions,
plus in (X) i need compare last value with new one.
Yes, this alsready exists in e.g.:
Boost Signals2
http://www.boost.org/doc/libs/1_59_0/doc/html/signals2.html
There are many samples that should get you going.
Signals2 does offer thread safety, but I guess that doesn't harm.
Alternatively,
Qt
Qt does have a signals/slots implementation, as do many other UI frameworks:
http://doc.qt.io/qt-4.8/signalsandslots.html
I want to dynamically instantiate a QWidget and bind its "Pressed" event, either with a Qt signal or by overriding a function.
However I'm only allowed to create one new .cpp file.
I don't know how to override a C++ function dynamically, or how to change a virtual function into a Qt signal.
Is what is represented in the picture above achievable ?
The Widgets Tutorial of the Qt docs is a nice starting point.
Under Qt Widgets Examples you can find the Calculator Example, which should contain all of what you want to do.
Take the code, strip it down to what you need, use and try to understand it.
Or maybe have a look at the Getting Started section.
I'm currently starting to learn how to use C++ Builder. However, I'm stuck on doing something basic, which is to open a window when I click on an element of the menu. I'm ok with the event management, but when I try to display it with the method Show(), it's written when compiling that "the method is not reachable" (I have it in french so I'm not sure about the exact translation). I've tried it different ways, also with the popup element, but I always get this message. Here is the short code that I use to display the window :
TFrame1 * NewPageFormer = new TFrame1(this);
NewPageFormer->Show();
delete NewPageFormer;
NewPageFormer = NULL;
Do you have any idea where the problem comes from?
Thank you
Try with:
TForm1 * NewPageFormer = new TForm1(this);
NewPageFormer->Show();
What you should Show() is a TForm (e.g. take a look at How do I open a new form with a button, using C++ Builder?).
Frames are combinations of components placed on a form-like object, which are considered a cohesive whole.
A frame (TFrame), like a form, is a container for other components. It uses the same ownership mechanism as forms for automatic instantiation and destruction of the components on it, and the same parent-child relationships for synchronization of component properties.
However a frame is more like a customized component than a form, so you cannot directly call the Show() method of a frame.
I'm fairly new to Qt, and am trying to wrap my head around signals and slots. Though I've figured out how to create custom slots, I've yet to figure out how do update the GUI from my C++ code. I realized that the entire UI, which I created in the designer, is only written in what appears to be XML based UI code. Do I have to handwrite my own Qt C++ UI in order to update the interface, or can I somehow use C++ to update the XML based UI? I'm just looking to add a widget to the main form on a button click. Any help is appreciated. Thanks!
To add a widget to a form you can simply do
ui->layout()->addWidget(new Widget);
XML is used by QtDesigner as a mean to create, update, and persist your GUI, enabling a visual approach to development, but in the end you can build your application entirely without it.
you dont havfe to update the xml of UI . you can inherit the ui into your own class using setupUi
http://crpppc19.epfl.ch/doc/qt4-doc-html/html/qwidget.html#setupUi
now in your C++ class you can update the widgets like changing label text, lineEdit text, setting up spinbox value using Signals & slot.
That xml is used by Qt designer and outside of designer it's only used by uic as a source to generate C++ code, so everything that you do in the designer end-up as C++ code, so it can be updated (or done completely) in C++ code (you can look into the code and see that you most likely have a member called ui that is most likely a pointer, but it can also be an instance of a C++ class that is generated for you by uic, and trough that ui member you can access the widgets and layouts that you created in the designer).
A generic resource that i recommend you to read can be found here and then (if you still can't figure it out) ask a specific question about what exactly are you trying to achieve.
LE: that link contains 3 methods to use the generated code into C++ code, don't try all of them into your working project, you may choose one method or use the default one (ui member pointer)