I am writing a C++ application using GTK and OpenGL. I have a GTK builder which reads an XML file and builds itself. I need to add an "OpenGL window area" into it. How do I do this?
The way I do it (gtkmm / C++ code) is like this:
#include <gtkmm.h>
#include <gtkglmm.h>
class GLWidget : public Gtk::GL::DrawingArea {
public:
GLWidget(Glib::RefPtr<Gdk::GL::Config> glconfig)
: Gtk::GL::DrawingArea(glconfig) {}
~GLWidget() {}
virtual bool on_expose_event(GdkEventExpose* event);
};
bool GLWidget::on_expose_event(GdkEventExpose* event)
{
Glib::RefPtr<Gdk::GL::Drawable> d = get_gl_drawable();
d->gl_begin(get_gl_context());
// make this as complex as you need
glClear(GL_COLOR_BUFFER_BIT);
d->swap_buffers();
d->gl_end();
return true;
}
int main(int argc, char **argv)
{
Gtk::Main kit(argc, argv);
Gtk::GL::init(argc, argv);
Glib::RefPtr<Gtk::Builder> builder = Gtk::Builder::create_from_file("ui.glade");
Gtk::Window* mainWindow;
Gtk::Alignment* container;
builder->get_widget("mainWindow", mainWindow);
builder->get_widget("Box", container);
if (mainWindow == NULL || container == NULL) {
g_critical("Gtk Builder failed to load mainWindow and/or container !\n");
return -1;
}
Glib::RefPtr<Gdk::GL::Config> glconfig;
glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA | Gdk::GL::MODE_DOUBLE);
if (!glconfig)
glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB);
if (!glconfig) {
g_critical("Cannot create OpenGL-capable config\n");
return -1;
}
GLWidget drawingArea(glconfig);
drawingArea.set_size_request(640, 480);
drawingArea.show();
container->add(drawingArea);
kit.run(*mainWindow);
return 0;
I.e. I'm simply loading a UI that contains an empty container widget, get the handle to that by name, then create the GL-enabled drawing area in code and add it to the empty container. Supposedly, it's possible to "load-time" substitute an ordinary Gtk DrawingArea for a GtkGL one (see this posting) but that method didn't work for me; the above, programmatically creating it, always did.
You need gtkglext / gtkglextmm for the GL Drawingarea widget.
Related
I have problem with my small app in Qt framework C++
I have a first window which there's two buttons where you can choose to play music or video. The music button will close the "choose window" and should open "music window" and similarly for video button.
I don't know how to do this... I know a way which I've leant and used but this method I'm going to explain how it doesn't fit to my current issue.
I've created a pointer of that window class in header of choose window and when the music button is clicked, I new the pointer and musicWindow->show(); and hide(); the choose window, this is good but there is a problem:
the new opened music window doesn't have any taskbar icon/thumbnail and when Its minimized there's no way to have that opened again(except wtih alt-tab)
and dont find a way to open it like a complete new window, I just can open all of them at once by using choosWindow.show(); / musicWindow.show(); /... .
I know there must be a way, but I dont even know what topics to search for to get further...
FirstWindow.cpp:
void FirstWindow::on_musicChoose_clicked()
{
//send a signal from here
}
void FirstWindow::on_videoChoose_clicked()
{
//send a signal from here
}
main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
FirstWindow w;
if(//what condition?)
{
MusicWindow mw;
mw.show();
}
if(//what condition?)
{
VideoWindow vw;
vw.show();
}
return a.exec();
}
I found my answer in Qt Forum:
https://forum.qt.io/topic/68602/child-window-in-taskbar/3
#Radek(Qt Forum): Try passing 0 (zero) as parent when you create them.
FirstWindow.cpp:
void FirstWindow::on_musicChoose_clicked()
{
this->hide();
mw = new MusicWindow(0); // passing nullptr as parent
mw.show();
}
void FirstWindow::on_videoChoose_clicked()
{
this->hide();
vw = new VideoWindow(0); // passing nullptr as parent
vw.show();
}
main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
FirstDialog w;
w.exec();
return a.exec();
}
Is it possible to prevent right-click from opening the default context menu on QGraphicsTextItem ? The menu with "Undo, Redo, Cut, Copy, Paste..". On Ubuntu 18.04, that is. I don't know how this behaves on Windows.
I have overridden the mouse press handler to eat right-clicks in my view and tried to do that also in the item class itself. This actually did prevent the menu on Qt 5.10.0, but for some reason not anymore on 5.11.1:
void EditorView::mousePressEvent(QMouseEvent * event)
{
if (event->button() == Qt::RightButton)
{
return;
}
...
doOtherHandlingStuff();
...
}
In the item itself it doesn't have any effect if I do this:
void TextEdit::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
event->ignore();
return;
}
You have to override the contextMenuEvent method of QGraphicsTextItem:
#include <QtWidgets>
class GraphicsTextItem: public QGraphicsTextItem
{
public:
using QGraphicsTextItem::QGraphicsTextItem;
protected:
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override
{
event->ignore();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene;
QGraphicsView w{&scene};
auto it = new GraphicsTextItem("Hello World");
it->setTextInteractionFlags(Qt::TextEditable);
scene.addItem(it);
w.show();
return a.exec();
}
How to capture the global keys in Ubuntu in Qt application. I need to handle the keys like Ctrl, Shift even my qt application is minimized state also. Looks like LibQxt supports this. But as per my understanding this library won't have any support from Qt4. I am using Qt5.7. Do we have any other way to do this ?
This can be achieved using x11/xcb. The idea is to listen to a specific keyboard shortcut, system-wide, using the XGrabKey function from xlib, then catching the corresponding xcb event in the overridden nativeEventFilter method of a QAbstractNativeEventFilter subclass.
As an example, let's activate an application minimized window, using the Ctrl-A shortcut from anywhere.
The project must reference the x11extra qt module, and link the x11 library:
QT += x11extras
LIBS += -lX11
This is the filter header:
#include <QAbstractNativeEventFilter>
#include <QWidget>
class EventFilter : public QAbstractNativeEventFilter
{
public:
void setup(QWidget *target);
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result);
private:
int keycode;
QWidget * target;
};
and this is the implementation:
#include <xcb/xcb.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <QtX11Extras/QX11Info>
void EventFilter::setup(QWidget *target)
{
this->target = target;
Display * display = QX11Info::display();
unsigned int modifiers = ControlMask;
keycode = XKeysymToKeycode(display, XK_A);
XGrabKey(display, keycode, modifiers, DefaultRootWindow(display), 1, GrabModeAsync, GrabModeAsync);
}
bool EventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *)
{
if (eventType == "xcb_generic_event_t")
{
xcb_generic_event_t* xcbevent = static_cast<xcb_generic_event_t *>(message);
switch(xcbevent->response_type)
{
case XCB_KEY_PRESS:
xcb_key_press_event_t * keypress_event = static_cast<xcb_key_press_event_t *>(message);
if(keypress_event->state & XCB_MOD_MASK_CONTROL)
{
if(keypress_event->detail == keycode)
{
qDebug() << "ACTIVATING ...";
target->activateWindow();
}
}
}
}
return false;
}
In a main, we create a widget on the fly, instantiate, install and setup our filter.
#include "eventfilter.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.setGeometry(100, 100, 400, 300);
w.show();
EventFilter filter;
a.installNativeEventFilter(&filter);
filter.setup(&w);
return a.exec();
}
If the user minimize the widget, or the widget is deactivated, the Ctrl-A shortcut should prompt it back to the foreground.
Please notice that the XGrabKey call from the setup method could fail if some other x client grabbed the same key combination, already.
Also notice that extra modifier masks will be delivered in the event state field if some lock keys are on (e.g. on my system the pressed caps lock yelds an extra XCB_MOD_MASK_LOCK, and the num lock an extra XCB_MOD_MASK_2).
I am trying to associate custom files with an osx app. I have a plist that associates files with the app, but double clicking a file opens the app with no data inside.
Calling
someapp.app/Contents/MacOs/someapp somefile.abc
from the terminal opens the file correctly inside the app.
MyApp::MyApp(int& argc, char**argv): QApplication(argc, argv)
{
...
m_MainWindow = new MainWindows();
m_MainWindow->show();
if(argc > 1 && argv[1])
m_MainWindow->openFile(QString(argv[1]);
else
m_MainWindow->showStartupDialog(); // to create a new document
}
Searching around I found that I should somehow implement QFileOpenEvent... how ?
This example looks good... but I don't understand how to combine the constructor and the event...
How do I make this work ?
(OS X 10.6-10.9, app created using Qt 4.8)
The following is the adapted code, that will respond to the OpenFileEvent either on start or during the normal functioning - and also allow opening o file from command line or creating a new file
MyApp::MyApp(int& argc, char**argv): QApplication(argc, argv)
{
...
m_MainWindow = new MainWindows();
m_MainWindow->show();
if(argc > 1 && argv[1])
m_MainWindow->openFile(QString(argv[1]);
else if (m_macFileOpenOnStart != "")
m_MainWindow->openFile(m_macFileOpenOnStart); // open file on start if it exists
else
m_MainWindow->showStartupDialog(); // to create a new document
}
// responds to FileOpenEvent specific for mac
bool MyApp::event(QEvent *event)
{
switch(event->type())
{
case QEvent::FileOpen:
{
QFileOpenEvent * fileOpenEvent = static_cast<QFileOpenEvent *>(event);
if(fileOpenEvent)
{
m_macFileOpenOnStart = fileOpenEvent->file();
if(!m_macFileOpenOnStart.isEmpty())
{
if (m_MainWindow)
{
m_MainWindow->openFile(m_macFileOpenOnStart); // open file in existing window
}
return true;
}
}
}
default:
return QApplication::event(event);
}
return QApplication::event(event);
}
i'm using a QApplication derived class that emits a signal when file is ready:
#ifndef OPENWITHAPPLICATION_H
#define OPENWITHAPPLICATION_H
#include <QApplication>
#include <QFileOpenEvent>
#include <QMessageBox>
class OpenWithApplication : public QApplication
{
Q_OBJECT
public:
QString fileName;
OpenWithApplication(int &argc, char **argv)
: QApplication(argc, argv)
{
}
signals:
void fileReady(QString fn);
protected:
bool event(QEvent *event)
{
if (event->type() == QEvent::FileOpen) {
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event);
fileName = openEvent->file();
emit fileReady(fileName); // the file is ready
}
return QApplication::event(event);
}
};
#endif // OPENWITHAPPLICATION_H
main.cpp connects created OpenWindowApplication with the MainWindow object so once the file is ready, the signal is emitted and received by it for processing
#include "mainwindow.h"
#include <openwithapplication.h>
int main(int argc, char *argv[])
{
OpenWithApplication a(argc, argv);
MainWindow w;
w.connectOpenWithApp(&a);
w.show();
return a.exec();
}
and MainWindow connects fileReady signal with a lambda func that opens the file and updates widget
void MainWindow::connectOpenWithApp(OpenWithApplication*app) {
connect(app, &OpenWithApplication::fileReady, [this](QString fileName){
bw->open(fileName);
bw->update();
});
}
here's the result:
I'm building a simple C++ application on Mac OS X 10.9 with Qt 5.2.1 using CMake (without MOC).
I am starting the executable from the command-line. The problem is that the menu bar is not showing up at all, the Terminal menu bar is still visible but not clickable. When I switch windows temporarily and then come back to the window of this application, I at least see the standard "application" menu with "About". The "About" action is now working and shows the dialog. The toolbar button also works as expected.
What else I tried (and didn't work):
using the pre-defined menuBar()
use setMenuBar()
new menuBar(0)
menubar->setVisible(true)
When I check the isVisible() it returns false, also if I set it to visible in the line before.
I wonder whether the lack of using MOC can be the reason for this?
Below I attached a reduced example.
#include <QtGui>
#include <QtWidgets>
class MainWindow : public QMainWindow {
public:
MainWindow();
private:
void create_actions_();
void create_menus_();
void create_toolbar_();
void about_();
QMenuBar* menu_bar_;
QMenu* file_menu_;
QMenu* help_menu_;
QToolBar* file_toolbar_;
QAction* action_about_;
};
MainWindow::MainWindow() {
resize(800, 600);
create_actions_();
create_menus_();
create_toolbar_();
}
void MainWindow::create_actions_() {
action_about_ = new QAction(tr("About"), this);
connect(action_about_, &QAction::triggered, this, &MainWindow::about_);
}
void MainWindow::create_menus_() {
menu_bar_ = new QMenuBar(this);
file_menu_ = menu_bar_->addMenu(tr("&File"));
menu_bar_->addSeparator();
help_menu_ = menu_bar_->addMenu(tr("&Help"));
help_menu_->addAction(action_about_);
menu_bar_->setNativeMenuBar(true);
}
void MainWindow::create_toolbar_() {
file_toolbar_ = addToolBar(tr("File"));
file_toolbar_->addAction(action_about_);
file_toolbar_->setIconSize(QSize(16, 16));
}
void MainWindow::about_() {
QMessageBox::about(this, tr("About"), tr("FooBar"));
}
int main(int argc, char **argv) {
QApplication app(argc, argv);
MainWindow main_window;
main_window.show();
const int exit_code = app.exec();
return exit_code;
}
CMakeLists.txt
FIND_PACKAGE(Qt5Core)
FIND_PACKAGE(Qt5Gui)
FIND_PACKAGE(Qt5OpenGL)
FIND_PACKAGE(Qt5Widgets)
FIND_PACKAGE(Qt5Declarative)
FIND_PACKAGE(Qt5MacExtras)
ADD_EXECUTABLE(main main.cc)
qt5_use_modules(main Core Gui Widgets Declarative MacExtras)
Thanks a lot in advance!
OK, solved the problem myself. It appears you cannot add a separator to the menubar.
Removing the menu_bar_->addSeparator(); solved the problem.