QT. QLabel perfomance - c++

In my application I have a file manager similar to the standart windows explorer.
The structure is:
QScrollArea
QWidget
EFile
EFile
EFile
etc...
Each EFile widget contains 5 QLabels. So when the count of files is more than 30 I have a little delay while they are being created. I decided to create only visible files and create hidden on scroll or resize when they become visible. But it's not a solution - the delay remained (although it decreased of course).
The question is how should I modify my application to remove the delay while showing files.

The answer is that you do not compose your custom widget of QLabels. Instead, you overwrite the paint() function and draw the texts/pixmaps with QPainter. It is not as much work as it sounds. There are tons of examples for that in the Qt examples/tutorials.

If it really is a file explorer you want to implement, you should consider using a QFileSystemModel in combination with a QTreeView as shown in the example here:
http://qt-project.org/doc/qt-4.8/qfilesystemmodel.html
This will save you a lot of trouble.

Related

Qt - Display animated GIF selected by QListWidget on MainWindow

thank you in advance for reading and help.
I'm trying to make a GIF manager based on a QListWidget where you can select a GIF from the list (using on_*_itemClicked, as you can see below) and it will appear the animated GIF in the space below the list (or sideways, doesn't matter).
void MainWindow::on_listOfURL_itemClicked(QListWidgetItem *item)
{
QLabel* lab = new QLabel(this);
QMovie* mov = new QMovie(":/res/giftest/C:/Users/Rober/Desktop/giftest.gif");
lab->setGeometry(200, 200, 200, 200);
lab->setMovie(mov);
lab->show();
mov->start();
}
GUI screenshot of the program
I've tried using the piece of code above, but it shows nothing. It is just a futile try of making it work, that's why the GIF path is the same, you needn't worry about it.
Honestly, I've search a lot of code in forums and this very website regarding GIFS and animations, and none of the things I've seen have worked for me.
How should I proceed? I guess I should use some graphics QWidget in the UI and link it with the function on_*_itemClicked so it takes the location of the image from the QListWidgetItem and displays where I pointed in the UI.
I've gotten the code pasted here by surfing the Mighty Google, and it brings me some doubts:
I create a QLabel with the MainWindow as parent. Okay, but where will it appear?
Can't I create in the Designer a widget that I can define where will it be and just make the GIF work?
I think I've explained myself correctly, if not just let me know.
EDIT: I think what I need is a QLabel that is inside the MainWindow, below the URL list. How do I shape that QLabel in QtDesigner and then take that same QLabel in code and manipulate it with the GIF?
I think, you need to include into .pro
QTPLUGIN += qgif
and show label->show();
Of course you can add things in designer. You can add custom widgets you create, but you need make special project that would make a "plugin" for Designer and build it in Release mode, then install plugin in proper plugin folder.
For that you should be sure, that those are added to .pro file:
CONFIG += plugin
TEMPLATE = lib
QT += widgets uiplugin
Then you need to declare and implement plugin derived from QObject AND QDesignerCustomWidgetInterface.
DO CHECK validity: mov->isValid() Code that relies on external sources being good eventually becomes source of little disasters. Program either need a plugin's .dll next to it or static plugin linked with it
When you installed Qt, you installed app called QtAssistant. Take advantage of it. It's great deal of help. as well as their forums and examples storage you got in Qt directory. Qt5 got plugin example online: http://doc.qt.io/qt-5/qtwidgets-tutorials-widgets-childwidget-example.html
Okay, I've found myself the answer. It was pretty silly actually:
I didn't realize I could select a QLabel created in QtDesigner using ui->label and manipulate it.
ui->label->setMovie(selectedGif);
selectedGif->start();
ui->label->show();
Novice mistakes...

Qt: QVideoWidget doesn't show up and disables all buttons within application OR extremely slows down the application

To make it clear the question is: Why, when I add a QVideoWidget to my application, all buttons become not clickable, the scrollbars don't work, and the comboboxes as well become not clickable? Is QVideoWidget disabling those functionalities? Or is that maybe (like I read in this SO question) QVideoWidget is extremely slowing down my application, just by being added to the application?
Now the details:
I really hope someone can help me with this. I'm trying to place a QvideoWidget into my desktop application with the following code (nothing special, just like in the tutorials):
// ...
// more code above for other things...
// main video-player widget
video_widget = new QVideoWidget;
video_widget->setMaximumHeight(100); // I could set any size here...this is not the point
video_widget->setMinimumHeight(100);
video_widget->setStyleSheet(STYLE_WIDGET_BG); // same background as the other widgets...
video_widget->setMaximumWidth(100);
video_widget->setMinimumWidth(100);
media_player = new QMediaPlayer(0, QMediaPlayer::VideoSurface);
TV_V_LAYOUT_MAIN_2->addWidget(video_widget); // #define TV_V_LAYOUT_MAIN_2 ui.lvl_4_tv2_h_1 --> this a layout inside another layout...
media_player->setVideoOutput(video_widget);
return; // this function is called inside the MainWindow constructor
So there are the situations:
1) Without adding the videowidget, everything works fine...
2) As soon as I add the QVideoWidget with the code above:
app overview
What happens?
The video player doesn't show up in any way. There should be at least the gray background like the other widgets, but nothing. Yet the buttons position lowers, so I guess the player was inserted...The problem is: all buttons (and I mean ALL buttons within my application) are disabled. So are the comboboxes and the scrollbar. By disabled I mean, when you click them, it doesn't normally "animate" like when a button is cliked, and the scrollbar doesn't scroll...
By the way the QVideoWidget is not places into the same layout as the buttons below. You can see the layout hierarchy here: Layouts with Qt Designer
I guess I'm missing something very simple. Anyone got the solution for me?
INFO: I'm programming with Visual Studio 2013 with Qt Add-In; I use only standard libraries; gstreamer is included in the project as well (nothing implemented yet).
OLD EDIT: it may be that the inserting of the video-widget extremely slows down the application, therefore giving the illusion that the scrollbar and the buttons don't work, just because it takes a lot of time for them to process the user interaction. Is this possible? Any solution for that?
Got the solution:
If your QVideoWidgets or QMediaPlayers extremely slow down your application, all you have to do, if you haven't yet, is to move all (or just the nedeed) Qt dll's into your project folder.
That's very basic, I know, yet that was my problem. Now it works like heaven.

Changing application's main window GUI layout to be in code

In my application the main window's GUI is designed in the Qt-Creator designer. I have had some trouble in getting it to look just the way I'd like, but I can when doing the GUI in C++ code.
So, I plan to change the application's main window to be laid out in code.
What should I keep in mind when doing this?
How do I make sure all the menu items and button clicks etc. get migrated, too?
In my Qt experience I almost always write layout in code and here is what I can suggest:
a) Spend some time thinking which Layout to use, personally I tend to use either QGridLayout or nested QHboxLayout and QVBoxLayout which give you lot of flexibility.
b) I normally declare all child widgets as class variables always pointers and I create the real objects in the Main windows constructor.
About not to forget any control I suggest to print the XML of the UI file and draw a line on each control you recreate in the code.
As a good starting point, simply copy-pase the setupUi method from the ui_xxx.h file that uic had generated for you. You can then manually edit the setup code to suit your needs.

Gtkmm 3.0 How to switch between frames or windows

I'm rather new to C++, I have a bit of experience with MCV programming in Java. im using GTKmm on C++
What I'm trying to do is writing an application for teaching assistants to submit and edit applications to various positions, and administrators to come in view, and accept these applications.
What I'm trying to do at the begging is create 3 'frames' (I'm working on the submitting application for students only at the moment)
This first will have 2 buttons 1 for selecting if you're a student/admin
Upon clicking you're a student I want to hide this frame and show my second frame
The second frame will have another 2 buttons one for creating an application, and the other for editing applications
My core problem is that I don't understand how to switch between the frames, I've written all the code for my Model, and understand everything I want it to do however I cant seem to find how to do this...
My only idea would be to create windows for each of these, make them look all nice w/e, then when a button is pressed have that window close and a string written to file I can access to see which button has been pressed, then open a new window accordingly. Should I do it like this or is there a better way?
I think I can suggest a better/more idiomatic option for any version >= GTK+ 3.10 - which, to be fair, arrived about half a year after the accepted answer.
If you want to switch between widgets one-at-a-time without any accessories like tabs, then a Gtk::Stack seems like a better option. Because it's specifically geared for one-at-a-time presentation, without any redundancy and (theoretical) overhead from a Notebook's manual tabbing features, which you'd just be disabling straight away! It's a container with multiple children, with one visible at any given moment, and of course methods to change the active child.
You can hook up your own widgets and/or events to manage which of the Stack's children is shown. Alternatively - albeit possibly just restoring the redundancy in this case - there's a StackSwitcher companion widget, which is pretty much a vertical tab-bar as seen in the GTK+ demo and GNOME Tweak Tool.
Easiest way is to use a Notebook widget. You can hide the tabs since you will be controlling which page is showing, using method set_show_tabs(false). Put the top level widget for each of your frames in a pane using method append_page(), and switch between them using set_current_page(). You might want to hide the notebook's bevel if it's distracting, using method set_show_bevel(false).
Use signals to make a widget (e.g. "I'm a student" button) on one page do something (e.g. go to the second page). If you don't know what this means or how to do it, go through the gtkmm tutorial, it will explain this and more.
A bit too late ! But here is my try :
Gtk::Notebook is great but it is not ideal in switching between app frames on menu item clicks. Gtk::Stack, since gtkmm 3.10, exists to mitigate this. Assuming you're using glade and Gtk::Builder :
class
class AppName : public Gtk::ApplicationWindow
{
public:
//...Your app methods and callbacks
void on_mb_itemname_selected(); // The call back for our menu item click/select
private:
//Builder which will help build the app from a .glade file
Glib::RefPtr<Gtk::Builder> _builder;
//...
//Your menu item to activate a particular frame
Gtk::MenuItem * _mb_itemname;
//Your handle to Gtk::Stack which is usually the stack for the whole app
Gtk::Stack * _app_stack;
//...
}
constructor
AppName::AppName(BaseObjectType *cobj,
Glib::RefPtr<Gtk::Builder>& ref_builder)
:Gtk::ApplicationWindow(cobj),_builder(ref_builder)
{
//.. Other setup
_builder->get_widget("your_glade_id_to_stack",_app_stack);
_builder->get_widget("your_glade_id_to_menu_item",_mb_itemname);
// Connect signal_select of our menu item to appropriate signal handler.
mb_itemname->signal_select().connect(
sigc::mem_fun(*this,&AppName::on_mb_itemname_selected));
}
our callback
void AppName::on_mb_itemname_selected()
{
// Change the visible child of the stack concerned.
Gtk::StackTransitionType ttype = STACK_TRANSITION_TYPE_NONE;
_app_stack->set_visible_child("your_widget_name",ttype);
// Note that widget name is not widget glade id.
// You can set your widget under name Packing -> Name
return;
}

How to avoid ugly overlap with too many dockwidgets in QMainWindow?

In our application, we have a variable number of dockwidgets because some of them are added by plugins that are loaded at runtime. Not all dockwidgets need to be visible at the same time necessarily. This depends strongly on what the user is working on and what plugins are active.
However, if too many dockwidgets are added programmatically with addDockWidget(...), they start to overlap each other (not in terms of tabs, but in terms of content of one being painted on the area of a different one, which obviously looks broken).
The user can move the dockwidgets to dockareas that still have space left, but the layout/main window successfully prevents (untabbed) re-addition to the "crowded" dockarea.
We do allow tabbed docks to allow the user to arrange the dockwidgets a required, but we don't want to enable QMainWindow::ForceTabbedDocks since this would constrain the number of simultaneously visible dockwidgets too much (one per dock area).
How can I prevent this or better control how dockwidgets are added?
Not answering your question directly but it might be worthwhile to actually forget about Qt and actually think of how the whole interaction should work. What are the user expectations? What should actually happen if 10 different plugins become active? Should they be docked or should they be floating or should they become pin-able docking windows with initial state as a small button on the MainWindow edges? I think once you do that ground work and come up with user interface mock-ups, you can then start looking at Qt and figure out if Qt provides a direct way to develop that interface and if not what additional components you will need to develop to get that interface working.
From my own experience, I had developed a similar interface long back but in MFC. The way we did it was that some of the docked windows were deemed to be must have and they would come up as docked. Then there were a set of windows that didnt need to be visible always but should be quickly available and their initial state was as hidden pin-able dock window which meant they came up as buttons on the MainWindow edge. Finally there was a third set that was not required by the user always and could be called in from File->View Menu. Once the user made it visible, the user typically would assign it to one of the first two groups or keep it afloat. This whole configuration was saved in a config file and from there onwards whenever the plugin was loaded/became active the last used state of the associated docking window was used. It though involved quite a bit of extra work but the end result was to the satisfaction of all users.
Have you tryed setDockOptions(QMainWindow::AllowNestedDocks)? I can't test it now but it may help.
By default, QMainWindow::dockOptions is set to AnimatedDocks | AllowTabbedDocks so you would want something like
setDockOptions(QMainWindow::AllowNestedDocks | QMainWindow::AnimatedDocks | QMainWindow::AllowTabbedDocks)
EDIT:
If you are having too many problems, you may be going about this the wrong way. Instead of using docks, you may want to try using QMdiArea with QMdiWindow. This may not work for your program, but its something to think about.
This is the solution I tried:
I created in QTCreator an empty project with a window, a minimalistic menu labelled "New Dock" and a DockWidget named dockWidget
This is the triggered() handler for my menu item:
void MainWindow::on_actionNew_Dock_triggered()
{
QDockWidget* w = new QDockWidget("Demo", ui->dockWidget);
this->addDockWidget(Qt::LeftDockWidgetArea,w);
this->tabifyDockWidget(ui->dockWidget,w);
}
tabifyDockWidget(QDockWidget* first, QDockWidget* second) is a QMainWindow method that stacks the second dockwidget upon the first one. Hope it helps...