gtkmm centering widget in Gtk::Layout - c++

I'm trying to create a fullscreen window covered with an image and one entry widget in the middle of the window.
I already have the fullscreen window with the image, however, I'm struggling with positioning the entry box exactly in the middle of the window. I tried Gtk::Alignment, Gtk::VBox, Gtk::HBox, Gtk::Table
and many other containers, but to be honest, I don't really understand all the containers how do they behave. I am used to WIN32 API with absolute positioning and this is way different. I know I can use something like fixed positioning in Gtk/gtkmm, however, it does not seem like the cleanest solution to me.
class App : public Gtk::Window {
public:
[...]
App() {
fullscreen();
Gdk::Rectangle rec = get_screen()->get_monitor_workarea(get_screen()->get_primary_monitor());
set_default_size(rec.get_width(), rec.get_height());
show();
m_bgImage.set("image.jpg");
m_layout.add(m_bgImage);
m_entry.set_size_request(300, 30);
m_entry.set_opacity(0.5);
m_entry.set_visibility(false);
m_entry.signal_activate().connect(sigc::mem_fun(*this, &PadlockGui::onPasswordEntryReturn));
m_entry.set_icon_from_icon_name("edit-clear", Gtk::ENTRY_ICON_SECONDARY);
m_entry.signal_icon_press().connect(sigc::mem_fun(*this, &PadlockGui::clearPasswordEntry));
m_layout.add(m_entry);
add(m_layout);
show_all_children();
}
private:
Gtk::Layout m_layout;
Gtk::Image m_bgImage;
Gtk::Entry m_entry;
[...]
};
Here is a picture of my current situation:
Here is what I am trying to achieve:

I would suggest using CSS to create the background image rather than Gtk::Image. Then you can just put the entry directly in the window, and make sure its expand property is set to false and its halign and valign properties are centered.

Related

How to draw a caret/arrow bottom of a QDialog on qt5

I want to draw a caret / arrow top or bottom of a qt window. I cannot find any document regarding to this.
How can I accomplish this task with qt5? I've searched all possible words but can't find anything.
Can this be applied to QDialog or qml needed? My first choice is QDialog since I have a webengine and other qwidgets already in a QDialog.
I'm using C++.
Here is what I mean:
Most window-managers don't support non-rectangular windows directly, which means that if you want to do something like this you'll need to fake it by making the window large enough to include both its normal content and the desired caret-shape inside the window-area, and making the window transparent at the top.
To do that, call setAttribute(Qt::WA_TranslucentBackground) and setAttribute(Qt::WA_FramelessWindowHint) on your dialog, and override paintEvent(QPaintEvent *) to paint the dialog's background only for the parts of the dialog you want to be non-transparent.

How do I design a swipe/slide function in Qt to select a widget?

I would like to create a GUI interface as per the attached pic
[
My main issue is the central slider widget..as you can see I would like to create a function choosing widget that the user can slide left and right then click on the desired cook function..
Unfortunately it has to be done with Qt C++ widget not QML.
There are many ways to accomplish that.
One would be arranging the small widgets next to each other manually, using setGeometry(). Overlay the complete visible area of the parent with a transparent widget. Reimplement the mouseEvents in that overlay and use the move, press click events to decide how to move the small widgets (by repeatedly calling setGeometry on them with other coordinates) or whether one has been clicked.
Should be very lightweighted and straight forward to implement and allows complete control. Would be also easy to change the sizes by calling setGeometry) with a different size to model a fluid zoom effect. E.g. to have the center widget bigger than the peripheral.
You may also have a look at QScroller which should help you with the scrolling control.
How about Qt gestures ? Haven't used it but looks like your use-case.
reference:
http://doc.qt.io/qt-4.8/gestures-overview.html
http://doc.qt.io/qt-4.8/qswipegesture.html
You could capture the gesture on your widget and do actions like:
bool ImageWidget::gestureEvent(QGestureEvent *event)
{
if (QGesture *swipe = event->gesture(Qt::SwipeGesture))
swipeTriggered(static_cast<QSwipeGesture *>(swipe));
return true;
}
void ImageWidget::swipeTriggered(QSwipeGesture *gesture)
{
if (gesture->state() == Qt::GestureFinished) {
if (gesture->horizontalDirection() == QSwipeGesture::Left) {
// highlight the right widget , you could even bring it to center
} else if (gesture->horizontalDirection() == QSwipeGesture::Right) {
// highlight the left widget , you could even bring it to center
}
}
}

Custom UI for child window in Qt

I've been doing some test with Qt 5 using C++ and I saw a lot of potential! But I came to a big wall which I haven't been able to pass yet.
I want to make a widnow that contains other windows (MDI), and I follow some of the tutorials online but the window is created by code, and I don't know how to "link" it to an UI file that I already design.
I follow the MDI tutorial that comes with Qt Creator, it works fine, but as I said before it doesn't work with custom UIs. And I found this other one that is exactly what I want, I follow it and it doesn't work I also downloaded the source code from the example, run it and still doesn't work. It opens a window with nothing in it.
If some one has an example, a good tutorial or a book that comes with the right info, I'll appreciate it.
Thanks a lot for taking the time to read this.
You should place a QMdiArea widget on your window. It provides an area in which MDI windows are displayed. It can be done via designer.
All your subwindows should inherit QMdiSubWindow which provides a subwindow class for QMdiArea :
class MyWindow : public QMdiSubWindow
{
Q_OBJECT
public:
explicit MyWindow(QWidget *parent = 0);
~MyWindow();
};
After creating a custom subwindow you can add it to the MDI area like:
MyWindow * subWindow = new MyWindow(ui->mdiArea);
MyWindow->show();
You can also add subWindows in designer by right clicking on the MDI area and choosing :
"Add subWindow"
This will add a subwindow which is viewable in designer. You can also add arbitrary widgets to the added subwindows in designer this way.

How to Layer independent widgets in Qt?

I'm creating an application using Qt which consists of a widget that is used as the background of the application, and a user control interface that is floating above.
A similar example is google maps, where the map is on the background and the controls are on top of the background.
But the thing is that the background widget can be changed to a different widget (there's a widget that displays a map, another widget that displays video feed, ...)
And the same thing happens for the buttons in the user control interface, they are not directly related to the current background and can be change dinamically.
I've tried using a QStackedLayout, using two layers, the background widget and the user control interface. But you cannot interact with the background layer because all the clicks are blocked by the widget in the front.
Any suggestions?
You could place a filter on the event stream to your interface widgets using the QObject::installEventFilter() function, and intercept all the incoming mouse-click events. Once you have captured these events, use the filter function to delegate them to either the background widget, or deliver them to the front interface buttons. You would most likely have to use the (x,y) coordinates of the mouse-click to determine if an event should go to the background widget, or one of the foreground button widgets.
Another option is to create a derived class from QAbstractButton (or whatever QWidget you're using for your buttons), and re-implement the event functions for mouse-clicks on that widget (i.e., QAbstractButton::mousePressEvent(), etc.). When a mouse-click arrives, check to see if the mouse was over the button, and if it wasn't, send the event to the background widget via a signal or QCoreApplication::sendEvent().
Your question is too generic to give you a especific answer, but the most obvious solution is to implement classes that inherits from QWidget for each possible component of you system. In your example I can visualize 2 distinct components: Background and Controls. Background would store all the image data, like maps and videos, while the Controls would have the buttons to interact with the system. You can even break the Background into different classes to manage image or video. I recommend using a central GUIController class that inherits from QObject to manage all the interface interactions, like connecting the signals/slots or implementing any animations, this way you can add/manage multiple widgets without going trough different .cpp's.
EDIT: With your comment, seems that your main problem is that your mouse events are not propagating to your widgets as you expected. Probably the reason for this is that you are not setting the parent/children relationships between the components. Make sure that you are calling the default QWidget constructor in your custom widgets classes like above:
CustoWidget(QWidget *parent = 0, Qt::WFlags flags = 0) : QWidget(parent, flags)
{
//your code here
}
When creating the Controller class, sets the right relationships between the components. In the context of your system, seens to me that all components will be added as Background children, so it would looks like below:
class Controller : public QObject
{
public:
Controller(QObject *parent = 0, Qt::WFlags flags = 0) : QObject(parent, flags)
{
wdg_back_= new BackWidget(this);
wdg_control_ = new Controls(wdg_back);
wdg_1_ = new GenericWidget(wdg_back);
//connect your signals/slots, etc
}
private:
BackWidget *wdg_back_;
Controls *wdg_control_;
GenericWidget *wdg_1_;
}
Ok I've finally found a solution for my issue.
My approach of using QStackedWidget was wrong, widget on the background are not meant to be clickable, and even though it might be done, it's not what I was looking for.
In the end, this is what I've done:
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
MapView *backgroundWidget = new MapView(centralWidget);
backgroundWidget->setMinimumSize(1024,600);
QGridLayout *controlsLayout = new QGridLayout(centralWidget);
MyControlWidget *control1 = new MyControlWidget(centralWidget);
control1->setMinimumSize(140,140);
control1->show();
controlsLayout->addWidget(control1,2,0);
So I create a QWidget, centralWidget which will be the parent of the background and the foreground. Set the background to full screen, and organize the controls in a QGridLayout, which doesn't affect the backgroundWidget.
If I click on a control, the event is processed by this control, but clicking on an empty space will trigger a mouse event on the backgroundWidget, which is what I needed.
I'll test this for some time and if it works fine I'll close the question.

Making a window a desktop in XLib/Qt

I am trying to write a simple program to act as my desktop background in Qt, I have made it all work fine apart from making it a Desktop Widget. I have no idea on how to do this, I don't mind using XLib or Qt for doing this, but if anyone has some suggestions I would be very happy.
I have created a simple example that will fill the desktop background white. It is easy to make it draw an image.
class DesktopWidget : public QWidget
{
Q_OBJECT
public:
DesktopWidget()
{
setAttribute(Qt::WA_X11NetWmWindowTypeDesktop);
resize(QApplication::desktop()->size());
}
protected:
void paintEvent(QPaintEvent*)
{
QPainter painter(this);
painter.fillRect(geometry(), Qt::white);
}
};
The problem with this solution is that it completely paints over everything that your desktop environment draws in the background (including icons, plasmoids,...).
If you just want to set a new background image programmatically, I would check if your DE has an API for that.