Consider a QWidget, normally a child in some Layout.
Supposed I want to make it fullScreen for a while, then have it return to it's old spot.
QWidget::setFullScreen() requires that the widget needs to be an independent window - any ideas how to work it out?
The simplest way I can see is to reparent to 0. Something like this:
#include <QApplication>
#include <QPushButton>
class MyButton : public QPushButton
{
public:
MyButton(QWidget* parent) : QPushButton(parent) {}
void mousePressEvent(QMouseEvent*) {
this->setParent(0);
this->showMaximized();
this->show();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget mainWidget;
MyButton button(&mainWidget);
mainWidget.show();
return a.exec();
}
I have modified the previous example. The previous example never goes back to normal screen.
Just copy paste the code and it will run.
#include <QApplication>
#include <QPushButton>
class MyButton : public QPushButton
{
public:
MyButton(QWidget* parent) : QPushButton(parent) {
m_pParent = parent;
maxMode = false;
}
QWidget * m_pParent;
bool maxMode;
Qt::WindowFlags m_enOrigWindowFlags;
QSize m_pSize;
void mousePressEvent(QMouseEvent*) {
if (maxMode== false)
{
m_enOrigWindowFlags = this->windowFlags();
m_pSize = this->size();
this->setParent(0);
this->setWindowFlags( Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
this->showMaximized();
maxMode = true;
}
else
{
this->setParent(m_pParent);
this ->resize(m_pSize);
this->overrideWindowFlags(m_enOrigWindowFlags);
this->show();
maxMode = false;
}
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget mainWidget;
MyButton button(&mainWidget);
mainWidget.show();
return a.exec();
}
Related
The way I understand the qtreeview.cpp the expand method in the QTreeView is responsible for expanding nodes. For example it is used in the expandOrCollapseItemAtPos method. I try to redefine a node expansion in the QTreeWidget:
#include <QApplication>
#include <QWidget>
#include <QTreeWidget>
#include <QMessageBox>
class MyTree : public QTreeWidget
{
public:
MyTree(QWidget *parent) : QTreeWidget(parent) {}
expandItem(const QTreeWidgetItem *item) {
QMessageBox msg;
msg.setText("EXPAND ITEM!!");
msg.exec();
QTreeWidget::expandItem(item);
}
expand(const QModelIndex &index) {
QMessageBox msg;
msg.setText("EXPAND!!");
msg.exec();
QTreeWidget::expand(index);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget *mainWidget = new QWidget();
mainWidget->resize(200,100);
MyTree *myTree = new MyTree(mainWidget);
myTree->resize(200,100);
QTreeWidgetItem *node, *leaf;
node = new QTreeWidgetItem(myTree);
node->setText(0,"node");
leaf = new QTreeWidgetItem(node);
leaf->setText(0,"leaf");
mainWidget->show();
return a.exec();
}
But there is no any message box when I expand a node. I tried to comment QTreeWidget::expandItem(item); and QTreeWidget::expand(index); but expanding is still working.
How do I redefine a node expanding in a QTreeWidget?
QTreeWidget::expand and QTreeWidget::expandItem are non-virtual methods. So redefinition is not useful. I will use slot-signal mechanism with QTreeWidget::expanded/collapsed signals.
connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(myExpand(QModelIndex)));
This should solve your problem -
connect(QTreeWidgetObject, SIGNAL(itemExpanded(QTreeWidgetItem*)), SLOT(slotItemExpanded(QTreeWidgetItem*)));
Is it expected behaviour that QDialog::show() does not show the window if a parent has been set?
Background: I want to use QMetaObject::connectSlotsByName() to react to one of the dialogs signals, which means the parent-object needs to own it. Without the line marked as "This is the line in question" I get a runtime-message "QMetaObject::connectSlotsByName: No matching signal for on_child_accepted()". But with the line, the child dialog no longer appears.
#include <QtCore/QDebug>
#include <QtWidgets/QApplication>
#include <QtWidgets/QDialog>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QVBoxLayout>
class Parent : public QDialog
{
Q_OBJECT
public:
Parent(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags())
: QDialog{parent, f}
{
b.setText(tr("Show child"));
connect(&b, &QPushButton::clicked, [&]() {
c.show();
});
l.addWidget(&b);
setLayout(&l);
c.setParent(this); // This is the line in question
c.setObjectName("child");
QMetaObject::connectSlotsByName(this);
}
private slots:
void on_child_accepted()
{
qDebug() << "I got called";
}
private:
QPushButton b;
QDialog c;
QVBoxLayout l;
};
#include "main.moc"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Parent w;
w.show();
return a.exec();
}
This test fails on Qt 5.11 for Windows, from the MSYS2 64-bit build.
Any suggestions? Thank you in advance.
The dialog did actually appear, but not where you think it did: it is a non-window child widget of your window - it was transparent and yet it obscured most of the "Show Dialog" button, consuming all mouse events, and furthermore it was already shown since all children are shown when the parent is shown - so the button appeared to be non-functional for both of those reasons.
Setting a widget's parent clears its Qt::Window flag. Setting the dialog's background helps visualize the problem. Thus, you need to make the dialog a window after setting its parent.
The following reproduces your bug, and also demonstrates the fix.
// https://github.com/KubaO/stackoverflown/tree/master/questions/dialog-show-parenting-53208641
#include <QtWidgets>
class Parent : public QDialog {
Q_OBJECT
QVBoxLayout layout{this};
QDialog child;
QPushButton cShow{tr("Show child")}, cNonWindow{tr("Renew non-window child")},
cWindow{tr("Renew window child")};
Q_SLOT void on_child_accepted() {}
void reChild(bool makeWindow) {
child.~QDialog();
new (&child) QDialog;
Q_ASSERT(child.isWindow());
child.setParent(this);
child.setObjectName("child");
child.setStyleSheet("QWidget { background: blue }");
if (makeWindow) {
child.setWindowFlag(Qt::Dialog);
Q_ASSERT(child.isWindow());
} else {
Q_ASSERT(!child.isWindow());
child.show(); // The child gets shown when we're shown
}
QMetaObject::invokeMethod(this, &Parent::updateChild, Qt::QueuedConnection);
}
void updateChild() {
if (!child.isWindow()) child.move(50, cWindow.y() + cWindow.height() / 2);
this->update(); // Work around a refresh bug (affects OS X on 5.11 at least)
}
public:
Parent(QWidget *parent = nullptr, Qt::WindowFlags f = {}) : QDialog{parent, f} {
connect(&cShow, &QPushButton::clicked, [&]() { child.show(); });
connect(&cNonWindow, &QPushButton::clicked, [&] { reChild(false); });
connect(&cWindow, &QPushButton::clicked, [&] { reChild(true); });
for (auto *w : {&cShow, &cNonWindow, &cWindow}) layout.addWidget(w);
cNonWindow.click();
QMetaObject::connectSlotsByName(this);
}
};
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
Parent w;
w.show();
return a.exec();
}
#include "main.moc"
I'm trying to change the background color of a QMenu* object it does not work with setStyleSheet(), nor with setPalette().
I read this article but the guy says that I should add this line:
app.setStyle(QStyleFactory::create("fusion"));
I'm not sure what is app, I tried several combinations but it does not work.
Thanks!
You probably forgot to set QMenu's parent:
#include <QtGui>
class Window : public QWidget
{
public:
Window(QWidget *parent = 0) : QWidget(parent) {}
void contextMenuEvent(QContextMenuEvent *event)
{
QMenu menu(this);
menu.addAction(new QAction("Item 1", this));
menu.addAction(new QAction("Item 2", this));
menu.exec(event->pos());
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Window *window = new Window;
window->setStyleSheet("QMenu::item:selected { background-color: green; }");
window->show();
return app.exec();
}
It is necessary to list of directories by given path in QListView whith icons and checkboxes, then transmit names of marked folders to the program. For list directories i use code:
#include <QtGui/QApplication>
#include <QFileSystemModel>
#include <QListView>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFileSystemModel model;
QListView listView;
listView.setModel(&model);
listView.setRootIndex(model.setRootPath("C:\\Program Files"));
listView.show();
return a.exec();
}
How to add checkboxes and transmit it after pushing button?
Thanks.
There's nothing you can do that would fit in just a few lines. You can either derive from QFileSystemModel and add a checkbox column, or create a proxy model that will do the same.
Note that you can use built-in selection mechanism to Ctrl-click/⌘-click to expand the selection to multiple items:
//main.cpp
#include <QApplication>
#include <QFileSystemModel>
#include <QGridLayout>
#include <QListView>
#include <QPushButton>
#include <QMessageBox>
class Win : public QWidget
{
Q_OBJECT
QListView * view;
QPushButton * button;
public:
Win(QAbstractItemModel * model, const QModelIndex & idx) :
view(new QListView(this)), button(new QPushButton("List Selection", this))
{
QGridLayout * lay = new QGridLayout;
lay->addWidget(view, 0, 0, 1, 2);
lay->addWidget(button, 1, 0);
setLayout(lay);
view->setSelectionMode(QAbstractItemView::MultiSelection);
view->setModel(model);
view->setRootIndex(idx);
connect(button, SIGNAL(clicked()), SLOT(showSelection()));
}
public slots:
void showSelection() {
QString str;
foreach (QModelIndex i, view->selectionModel()->selectedIndexes()) {
str.append(i.data().toString());
str.append("\n");
}
QMessageBox::information(this, "Selected items", str);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFileSystemModel model;
Win v(&model, model.setRootPath("/"));
v.show();
return a.exec();
}
#include "main.moc"
I am trying to make a Collaborative Editor(I have to use Linux networking libraries for all the networking stuff), I have the main widget(custom made class that inherits QWidget) with all the components. In the constructor I create all the Widgets on this main Widget and at the end I try to create a new thread using QFuture(I use QFuture instead of QThread cause it allows me easily to call functions with any type of parameters, like QTextEdit, QTextCursor...) but it gives me this error at compilation:
"QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTextDocument(0x1b064b0), parent's thread is QThread(0x1985750), current thread is QThread(0x1ae7610)".
How to solve the error?
Here is my code:
mainwindow.h:
...//includes
using namespace QtConcurrent;
...
namespace Ui {
class Widget;
class TextEdit;
}
class TextEdit;
class Widget;
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
...
QFuture<void> thread;
}
class TextEdit : public QTextEdit {
Q_OBJECT
...
}
static void receiveKeyPress(TextEdit *textedit, QTextCursor *secondUserCursor) {
unsigned long long int Number = NULL;
QMessageBox::information(textedit->parentWidget(), "UI Component", "This makes the thread to throw the error");
while(1) if(connected == 1) {
read(recvFileDescriptor, &Number, sizeof(unsigned long long int));
if( Number != NULL)
if( Number == Qt::Key_Home )
secondUserCursor->movePosition(QTextCursor::StartOfLine);
...
else {
QTextCharFormat backgroundFormat = textedit->textCursor().charFormat();
backgroundFormat.setBackground(QColor("lightGreen"));
//If I don't use QMessageBox up there, it breaks here on the next command
secondUserCursor->setCharFormat(backgroundFormat);
secondUserCursor->setPosition(textedit->textCursor().position());
secondUserCursor->insertText(QString::number(Number));
} //else
}//while
}//the function
And mainwindow.cpp:
#include "mainwindow.h"
Widget::Widget(QWidget *parent) {
...
thread = run(receiveKeyPress, this->edit1, this->edit1->secondUserCursor); //run is from QtConcurrent namespace
}
main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget window;
...
window.show();
return a.exec();
}
I've read here on stackoverflow how others use QObject(which I never used and I don't get the idea of it) and QThread(the only combination) but I already tried to use QThread and I wasn't able to pass QTextEdit and QTextCursor to it.
Thanks in advance
Edit:
mainwindow.h
class TextEdit : public QTextEdit {
Q_OBJECT
...
public slots:
void receiveKeyPress(qulonglong);
...
};
mainwindow.cpp
void TextEdit::receiveKeyPress(qulonglong Number) {
if( Number == Qt::Key_Home )
...
}
recv-thread.h - created based on this link http://developer.qt.nokia.com/doc/qt-4.8/thread-basics.html#example-3-clock
#include <QThread>
#include "mainwindow.h" //To get TextEdit in here
class RecvThread : public QThread {
Q_OBJECT
signals:
void transferDataToSlot(qulonglong Data);
protected:
void run();
};
recv-thread.cpp
#include "recv-thread.h"
void RecvThread::run() {
unsigned long long int Number = NULL;
while(1) if(connected == 1) {
read(recvFileDescriptor, &Number, sizeof(unsigned long long int));
if( Number != NULL) {
emit transferDataToSlot(Number);
}
}
}
main.cpp
...
#include "recv-thread.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget window;
RecvThread recvThread;
...
QObject::connect(&recvThread, SIGNAL(transferDataToSlot(qulonglong)), window.edit1, SLOT(receiveKeyPress(qulonglong)), Qt::QueuedConnection); //line 38
recvThread.start();
//Displaying the window
window.show();
a.exec();
recvThread.quit();
recvThread.wait();
return 0;
}
Am I doing it right?