How to put osgEarth's ViewerWidget into an tabbed MdiArea? - c++

Is there something special about putting osgEarth's ViewerViewer into a QMdiArea? I created a QMdiArea as central Widget (called setCentralWidget) instead of taking osgEarth's viewer directly as central widget.
QMdiArea *mdiArea = new QMdiArea(this);
setCentralWidget(mdiArea); // call to QMainWindows method, snippet is taken from app's MainWindow
mdiArea->addSubWindow(viewerWidget); // this doesn't work, globe is not drawn
Everything I tried didn't worked... except osgEarth's ViewerWidget is set as central widget of my MainWindow. Also tried MultiViewerWidget without any success but because I need only one view the ViewerWidget should be ok, or not?
I had a look into the examples but didn't succed to use one of them as starting point.
Any hints? Thank's in advance.

you can try this, where Form1 is a QDialog
in main.cpp
int main()
{
QApplication a(argc, argv);
Form1 w=new Form1();//qdialog
.................//do something to initial the map
w.loadWidget(viewerWidget);
w.show();//the order of the loadwiget() and show() is important!!!!!
a.exec();
}
in Form1.cpp
void Form1::loadWidget(QWidget *qwidget)
{
qwidget->setMinimumSize( ui.mdiArea->width(),ui.mdiArea->height());
QMdiSubWindow * subW=ui.mdiArea->addSubWindow(qwidget);
subW->setWindowFlags(Qt::SubWindow | Qt::FramelessWindowHint);
subW->maximumSize();
}
This works well with qt 4.8.4+osgearth 2.3

Try setting the subwindow's geometry before starting the UI.
QMdiSubWindow* sw = mdiArea->addSubWindow(viewerWidget);
sw->setGeometry(...);
Otherwise OSG will probably become confused.
Got this answer by Gwaldron in the osgEarth forum here and it worked.
Also setting a minimum size for the viewerWidget will help (e.g. for positioning on TabWidget). See my question and answer here.

Related

How to add "status bar" to QT widget - without using QTDesigner

I am creating QT QEditText widget (C++) dynamically at run time.
I cannot use "static ways" AKA QTDesigner to add / design the widget - it is NOT a form.
I know "status bar" is used as default in "MainWindow".
I want to add same functions in QTextEdit.
The QT doc has an example of C++ code on how to use "status bar" in MainWindow - that is of little help.
I have added this code to the QTextEdit constructor
childStatusBar = new QStatusBar();
childStatusBar->setStatusTip(" Show current copy drag and drop text");
childStatusBar->showNormal();
childStatusBar->showMessage("Status test message");
It compiles and runs, but there is no "status bar".
I do not know what is missing in my code and would
appreciate an assistance in solving this issue.
(Links , references to code examples would be helpful)
Please make sure to
read the post
and replay with facts, not opinions.
Suggestion for alternates are NOT solutions.
Please avoid any format of "ask your friend", RTFM.
Been there, done that.
As far as Mt Higgins is concerned, I am not asking for editing my post - I am not
posting to get a lecture in English grammar or composition.
Cheers and
"... thanks for watching..."
Just create a Qt MainWindow or Widget example and create a statusbar on it. Build the project and you can find your ui_...h in your build directory. Open it and find the QStatusBar widget. You can copy from there.
Note: Layouts are very important in Qt. So don't forget main-widget / main-window main layout and it's relation with statusbar. And also statusbar's layout.
As we can see in QStatusBar document :
Typically, a request for the status bar functionality occurs in
relation to a QMainWindow object. QMainWindow provides a main
application window, with a menu bar, toolbars, dock widgets and a
status bar around a large central widget
So you need something like this code:
#include <QApplication>
#include <QMainWindow>
#include <QStatusBar>
#include <QTextEdit>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow *w = new QMainWindow();
w->resize(600, 400);
QTextEdit *textEdit = new QTextEdit(w);
textEdit->setStatusTip("Show current copy drag and drop text");
auto childStatusBar = new QStatusBar(w);
childStatusBar->showMessage("Status test message");
w->setStatusBar(childStatusBar);
w->setCentralWidget(textEdit);
w->show();
return a.exec();
}
and also QTextEdit has a setStatusTip function that you can add "Show current copy drag and drop text" there instead of childStatusBar.
NOTED: As I mentioned ‍QTextEdit‍ cannot have ‍QStatusBar as you use in your code.
Now, if you don't want to use this method(use QMainWindow ), you have to create a custom and personalized class for yourself.
This means that you have to write the StatusBar by yourself

How can i stop QT Widget from closing?

I have a class (Window) that inherits from QWidget (Not QMainWindow).
This is the important part of my main function.
QApplication app (argc, argv);
QMainWindow *window = new QMainWindow;
QMenuBar *tool_bar = new QMenuBar (window);
Window *graph_area = new Window (arguments);
window->setMenuBar (tool_bar);
window->setCentralWidget (graph_area);
window->show ();
app.exec ();
I thought that i would just override "closeEvent", but for some reason it doesn't get called when pressing the closing button.
I want to stop the user from closing the application if some process is still working.
Any ideas about how i might achieve that?
You can either:
Subclass QMainWindow, instead of QWidget
Override QMainWindow::closeEvent, instead of QWidget::closeEvent
Allocate your QMainWindow subclass on the stack, instead of on the heap, i.e.:
MyMainWindowSubclass window;
or:
Change your code to:
QApplication app(argc, argv);
Window w;
window->show();
app.exec();
and Window::closeEvent will be called.
Make your Window class an event filter and install it on the main window object. You’ll reimplement filterEvent method in Window. Do not forget to install it on the main window! And make sure that the filter filters the event out - the boolean result indicates whether you let the result through or filter it out. Look up the exact value needed to indicate either one - it’s a bad api and I never remember whether true or false does what I intend. It’s a classical case where an enumeration return value would work better, like Qt::Accept/Qt::Reject or some such.
I actually found another solution to my problem, that I find more pleasant. I can create a custom class mainwindow that inherits from QMainWindow and use it instead of QMainWindow. It might be more appropriate, because I will probably need some other changes to QMainWindow as well.

Set text for statusbar in QtDesigner?

By default, if I create a new Form in QtDesigner, of type "Main Window", I get three elements in there: centralwidget, menubar - which is not visible in Preview (Ctrl-R), unless actual menu entries are added; and statusbar.
The problem is - by default, the statusbar is the same background color as the rest, and so, when I do a Preview, I cannot really perceive whether the statusbar is there or not:
Basically, the only thing I can see is the "sizeGrip", which is not always easy to see - so I would like to have a text/message shown in the statusbar as well.
Now, I know that the API for QStatusBar Class has .showMessage used to show text in a statusbar - however, I cannot find any similar field in QtDesigner?!
So - is it possible to set a default/placeholder text in the statusbar in QtDesigner - and if so, how?
No, you cannot.
In QtDesigner, you can only set properties of a widget (see Q_PROPERTY), not invoke methods. The properties are listed in the Properties section of the documentation, and QStatusBar only has sizeGripEnabled (and the inherited properties from QWidget)
But what is the actual problem? You cannot clearly make out the status bar in the preview? The preview is supposed to help in checking singal/slots and layout constraints, not as a full functioning application.
There are also things that will influence the actual look&feel in the final application that cannot be checked in designer preview, like dynamic stylesheets, or custom styles.
if you want to check how your window looks like with text in the statusbar, you will need to make a mock-application that does just this: show some text
#include <QtCore>
#include <QtWidgets>
#include "ui_mainwindow.h"
int main(int argc, char **argv) {
QApplication app(argc, argv);
Ui::MainWindow ui;
QMainWindow wnd;
ui.setupUi(&wnd);
wnd.show();
ui.statusbar->showMessage("Hello World!");
return app.exec();
}

How does one split a QT(C++) UI into multiple widget subclasses and get it to display the same as all in the same class?

I'm learning QT (I already know C++ very well) and trying to get a UI to display well but I do not want to use the QT Designer that comes with QT Creator. I have the following class:
#include "MainPanel.h"
#include<QVBoxLayout>
MainPanel::MainPanel(QWidget *parent)
: QWidget(parent)
{
QLayout *lo = new QVBoxLayout(this);
mList = new QListWidget(this);
mList->addItem("Testing");
setLayout(lo);
lo->addWidget(mList);
lo->setSpacing(5);
}
The Main window class has a bunch of extra protected functions but the initControls method just does this:
void MainWindow::initControls()
{
QHBoxLayout *loMain = new QHBoxLayout(this);
loMain->addWidget(new MainPanel(this));
setLayout(loMain);
}
When I put all the code from MainPanel into MainWindow::initControls() or even in the constructor(either way), it works - shows a list widget with a single item "Testing". With the code in MainPanel though, it shows up as a very small rectangle that wouldn't fit the word "Testing" nor is there any semblance of text in there even partially.
I have tried to override sizeHint() in and move the code to create and return the list widget to a method getList() so I can access it from sizeHint too but that did nothing - I still get a small rectangle.
What am I doing wrong and what do I need to do or include to get the widget to paint properly? I have more controls I want to add to this UI (a button panel below the list widget and a detail panel on the right 2/3 of the window) but until I can get this to display, I can't possibly proceed with the rest.
I also want to do this entirely with code - not using the designer as I have vision issues and found it to be difficult to place things correctly on the form.
Someone please help - documentation and tutorials other than the documentation on QT's website is helpful if it points me to the right direction. I have already looked on QT's docs site under QWidget, QListWidget, QLayout, and QH(and V)BoxLayouts but see nothing and many of the tutorials talk about the designer.
Before someone tries to scold about creating a SSME or whatever small program - I have given you the smallest one that displays the issue - I know that putting the code all into the main window fixes it but one should never have everything in one class.
Okay, too unclear, what's happening there, we should have requested for more of your code =)
Here is the smallest possible sample, demonstrating what you should have been trying to achieve:
mainwindow.cpp:
#include "mainwindow.h"
#include "mainpanel.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
MainPanel* p = new MainPanel(this);
setCentralWidget(p);
}
mainpanel.h:
#include "mainpanel.h"
#include <QListWidget>
#include <QLayout>
MainPanel::MainPanel(QWidget *parent)
: QWidget(parent)
{
QLayout *lo = new QVBoxLayout(this);
QListWidget* mList = new QListWidget(this);
mList->addItem("Testing");
setLayout(lo);
lo->addWidget(mList);
lo->setSpacing(5);
}
main.cpp:
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.resize(400, 500);
w.show();
return app.exec();
}
Seemingly, you've tried to set a layout on QMainWindow, but it already has a built-in layout, it is exactly the case when setCentralWidget should work, leave manual layout creation for QWidget & QDialog subclasses.
The code above works fine, try it and refactor the way you want.
#MasterAler is correct that the root cause of your issue is setting a layout MainWindow. The reason for using a MainWindow is to support standard VBoxLayout of menubar, central widget, and status bar. So it makes no sense to set your own layout for a QMainWindow.
Since we didn't have your entire code, I didn't assume MainWindow was a QMainWindow. I got your code to work by making MainWindow a QDialog. This may be more of what you were originally looking for, where you want to put a widget of your own making into any container. Following is in Python (I find Python a faster prototyping environment than C++), but you can easily read it and see how to host your MainPanel is any widget (not just a MainWindow):
import sys
from PySide2.QtWidgets import QApplication, QWidget, QListWidget, QDialog, QVBoxLayout, QHBoxLayout
class MainPanel(QWidget):
def __init__(self, parent):
QWidget.__init__(self, parent)
lo = QVBoxLayout(self)
lo.setSpacing(5)
self.setLayout(lo)
mList = QListWidget(self)
mList.addItem("Testing")
lo.addWidget(mList)
class MainWindow(QDialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
loMain = QHBoxLayout(self)
loMain.addWidget(MainPanel(self))
self.setLayout(loMain)
if __name__ == "__main__":
app = QApplication(sys.argv)
# Show the form
window = MainWindow(None)
window.exec_()

setCentralWidget() causing the QMainWindow to crash.. Why?

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
this->setupUi(this);
this->setupActions();
this->setWindowTitle(tr("CuteEdit"));
label = new QLabel(tr("No Open Files"));
this->setCentralWidget(label);
label->setAlignment(Qt::AlignCenter);
}
By above code, I get a GUI like this(Its a screenshot of whole screen, Only observe the window displayed in middle of page of ebook). (I used QT Designer)
Now, i want user to select File->Open.. A Dialog appears and file gets selected.. Its contents are to be displayed in *textEdit widget..
Function for that is below..
void MainWindow::loadFile()
{
QString filename = QFileDialog::getOpenFileName(this);
QFile file(filename);
if (file.open(QIODevice::ReadOnly|QIODevice::Text))
{
label->hide();
textEdit->setPlainText(file.readAll());
mFilePath = filename;
QMainWindow::statusBar()->showMessage(tr("File successfully loaded."), 3000);
}
}
The window crashes at line:-
textEdit->setPlainText(file.readAll());
But if i comment the line:-
this->setCentralWidget(label);
i mean i remove label as being the central widget, the program runs as expected.. Why?
And also, I am not clear about the concept of CentralWidget. Pls guide.
JimDaniel is right in his last edit. Take a look at the source code of setCentralWidget():
void QMainWindow::setCentralWidget(QWidget *widget)
{
Q_D(QMainWindow);
if (d->layout->centralWidget() && d->layout->centralWidget() != widget) {
d->layout->centralWidget()->hide();
d->layout->centralWidget()->deleteLater();
}
d->layout->setCentralWidget(widget);
}
Do you see that if your MainWindow already had centralWidget() Qt schedules this object for deletion by deleteLater()?
And centralWidget() is the root widget for all layouts and other widgets in QMainWindow. Not the widget which is centered on window. So each QMainWindow produced by master in Qt Creator already has this root widget. (Take a look at your ui_mainwindow.h as JimDaniel proposed and you will see).
And you schedule this root widget for deletion in your window constructor! Nonsense! =)
I think for you it's a good idea to start new year by reading some book on Qt. =)
Happy New Year!
Are you sure it's not label->hide() that's crashing the app? Perhaps Qt doesn't like you hiding the central widget. I use Qt but I don't mess with QMainWindow that often.
EDIT: I compiled your code. I can help you a bit. Not sure what the ultimate reason is as I don't use the form generator, but you probably shouldn't be resetting the central widget to your label, as it's also set by the designer, if you open the ui_mainwindow.h file and look in setupGui() you can see that it has a widget called centralWidget that's already set. Since you have used the designer for your GUI, I would use it all the way and put the label widget in there as well. That will likely fix your problems. Maybe someone else can be of more help...
I'm not sure I understood your problem, neither what the guys above said (which I guess are valid information) and it seems to be an old topic.
However, I think I had a problem that looks like this and solved it, so I want to contribute my solution in case it helps anyone.
I was trying to "reset" central widget using QLabels. I had three different ones, switch from first to second, then to third and failed to switch back to the first one.
This is my solution that worked:
Header file
QLabel *imageLabel;
Constructor
imageLabel = new QLabel("<img src='/folder/etc.jpg' />");
this->setCentralWidget(imageLabel);
Reset
imageLabel = NULL;
imageLabel = new QLabel("<img src='/folder/etc.jpg' />");
this->setCentralWidget(imageLabel);
Hope that helps
Aris