Qt/win: showMaximized() overlapping taskbar on a frameless window - qt

I'm building an Qt-Application without the default window border as a frameless window.
The window functions are included by setting window flags in the QMainWindow like:
MainDialog::MainDialog(QWidget *parent):
QMainWindow(parent), currentProject(NULL), currentUser(NULL),
aViews(new QList<AViewForm*>()),
bViews(new QList<BViewForm*>()),
cViews(new QList<CViewForm*>())
{
ui.setupUi(this);
this->statusBar()->showMessage(tr(""));
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowSystemMenuHint);
...
}
The MainWindow has an .ui file within, thats why I cannot inherit from QDesktopWidget.
The Problem I have now is that the Appication overlays the windows taskbar when maximizing.
My Question now: is there any posibility to find out the available height of the OS desktop without the
availableGeometry().height()
-Method of QDesktopWidget? I cannot find anything in the documentation :(
Somebody else here asked a similar Question but used a QWidget instead of a QMainWindow.
I would be glad about any hints to my Problem

As you say you can use QDesktopWidget. If you don't have your class inherit from it you can create one in your constructor just for retrieving the height :
QDesktopWidget w;
int availableHeight = w.availableGeometry().height();

Guess thats not good practise, but i solved it as followed:
I built a new class which needs a MainWindow as param and with slots for the scaling actions:
FullScreen::FullScreen(QMainWindow &mainWindow, QObject *parent) : QObject(parent), mainWindow(mainWindow)
{
this->saveCurrentPosition();
}
void FullScreen::maximize()
{
this->saveCurrentPosition();
mainWindow.move(QApplication::desktop()->mapToGlobal(QApplication::desktop()->availableGeometry().topLeft()));
mainWindow.resize(QApplication::desktop()->availableGeometry().size());
}
void FullScreen::normalize()
{
mainWindow.move(lastGlobalPosition);
mainWindow.resize(lastSize);
}
void FullScreen::saveCurrentPosition()
{
lastGlobalPosition = mainWindow.mapToGlobal(mainWindow.rect().topLeft());
lastSize = mainWindow.size();
}
The only Problem which now occures is when the application is fullscreen and you move the taskbar. I have not set any resizeEvent though

Related

How to make QToolButton go beyond the edge of QToolbar?

How can I make the button go beyond the edge of QToolbar?
Below is the code as I create the toolbar:
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0)
private:
QToolBar* _toolBar;
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
_toolBar = new QToolBar;
QAction *actionAdd = new QAction(QIcon(":/images/add.png"), "", this);
_toolBar->addAction(actionAdd);
addToolBar(Qt::ToolBarArea::TopToolBarArea, _toolBar);
}
style.qss
QToolBar {
background: #018ac4;
height: 150px;
}
As said before, it is not possible to solve this correctly using QtWidgets.
However I see two options to visually create that effect:
Take the button out of the tool bar and add it to the main window instead, but do not add it to a layout. Usually i would say reposition it on resize events, but since it is in the top left, you might as well just call setGeometry() once on startup and not worry about it later. You probably have to add last, or call rise() though.
Make it look like the button sticks out, while it really doesn't. Make the toolbar as large as the button, but paint the lower part of the toolbar in the brighter blue, so that it looks like it is part of the widget below it.
It is not possible with widgets. A QWidget can not paint outside of its area. See this answer : https://stackoverflow.com/a/48302076/6165833.
However, the QToolBar is not really the parent of the QAction because addAction(QAction *action) does not take the ownership. So maybe the QMainWindow could paint your QAction the way you want but AFAIK this is not doable through the public API of Qt.
What you could do is use QML (but you would need to use QML for the whole window then).

Allow Close Option in Taskbar When QDialog is Open above QMainWindow

I have tried with setModel(false) but that is not the solution allowing that hampering other functionalities .So Now
I have one QMainwindow and QDialog pops up after clicking button on QMainwindow and I want to close the QMainWindow from Taskbar.
void on_btnShare_clicked()
{
auto hilightReelDlg = new HighlightReelDialog( this->highlightManager,
this->soloshotAnalyzer->getNoVideoArea(),
this->videoFilePaths,
this->SortingOptions,
this );
ui->btnShare->setEnabled(false);
if (hilightReelDlg != NULL )
{
int NumberHilights = this->mainAppLinker->getHighlightJumper()->getActiveHighlightCount();
ui->hilightProgressBar->setMaximum(NumberHilights);
QObject::connect(hilightReelDlg, &HighlightReelDialog::send_Init_Progress, this, [=](int inc)
{
on_Hilight_Init_Progress(inc);
});
QObject::connect(hilightReelDlg, &HighlightReelDialog::initialization_finished, this, [=]() { on_Hilight_Init_Finished(); });
hilightReelDlg->ProcessVideoPlayers();
//QDesktopWidget Class
QDesktopWidget desk;
QRect screenres = desk.screenGeometry(0);
hilightReelDlg->setGeometry(QRect(0.10*screenres.width(), 67, 0.79*screenres.width(), 0.86*screenres.height()));
hilightReelDlg->setModal(false);
hilightReelDlg->show();
}
ui->btnShare->setEnabled(true);
}
Praveen Kumar
You can try create QDialog with null parent insead of pointer to mainwindow. Is this case dialog will not block mainwindow. But I am sure you shouldn't do that, because in such case you will broke default behavior, which everybody used to use.

Hide QLineEdit blinking cursor

I am working on QT v5.2
I need to hide the blinking cursor (caret) of QLineEdit permanently.
But at the same time, I want the QLineEdit to be editable (so readOnly and/or setting editable false is not an option for me).
I am already changing the Background color of the QLineEdit when it is in focus, so I will know which QLineEdit widget is getting edited.
For my requirement, cursor (the blinking text cursor) display should not be there.
I have tried styleSheets, but I can't get the cursor hidden ( {color:transparent; text-shadow:0px 0px 0px black;} )
Can someone please let me know how can I achieve this?
There is no standard way to do that, but you can use setReadOnly method which hides the cursor. When you call this method it disables processing of keys so you'll need to force it.
Inherit from QLineEdit and reimplement keyPressEvent.
LineEdit::LineEdit(QWidget* parent)
: QLineEdit(parent)
{
setReadOnly(true);
}
void LineEdit::keyPressEvent(QKeyEvent* e)
{
setReadOnly(false);
__super::keyPressEvent(e);
setReadOnly(true);
}
As a workaround you can create a single line QTextEdit and set the width of the cursor to zero by setCursorWidth.
For a single line QTextEdit you should subclass QTextEdit and do the following:
Disable word wrap.
Disable the scroll bars (AlwaysOff).
setTabChangesFocus(true).
Set the sizePolicy to (QSizePolicy::Expanding, QSizePolicy::Fixed)
Reimplement keyPressEvent() to ignore the event when Enter/Return is hit
Reimplement sizeHint to return size depending on the font.
The implementation is :
#include <QTextEdit>
#include <QKeyEvent>
#include <QStyleOption>
#include <QApplication>
class TextEdit : public QTextEdit
{
public:
TextEdit()
{
setTabChangesFocus(true);
setWordWrapMode(QTextOption::NoWrap);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
setFixedHeight(sizeHint().height());
}
void keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
event->ignore();
else
QTextEdit::keyPressEvent(event);
}
QSize sizeHint() const
{
QFontMetrics fm(font());
int h = qMax(fm.height(), 14) + 4;
int w = fm.width(QLatin1Char('x')) * 17 + 4;
QStyleOptionFrameV2 opt;
opt.initFrom(this);
return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h).
expandedTo(QApplication::globalStrut()), this));
}
};
Now you can create an instance of TextEdit and set the cursor width to zero :
textEdit->setCursorWidth(0);
Most straight forward thing I found was stolen from this github repo:
https://github.com/igogo/qt5noblink/blob/master/qt5noblink.cpp
Basically you just want to disable the internal "blink timer" Qt thinks is somehow good UX (hint blinking cursors never were good UX and never will be - maybe try color or highlighting there eh design peeps).
So the code is pretty simple:
from PyQt5 import QtGui
app = QtGui.QApplication.instance()
app.setCursorFlashTime(0)
voilà.
Solution in python:
# somelibraries
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.layout = QVBoxLayout()
self.setFocus() # this is what you need!!!
container = QWidget()
container.setLayout(self.layout)
# Set the central widget of the Window.
self.setCentralWidget(container)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
I ran into the same problem but setReadOnly is not a viable option because it alters the UI behavior in other places too.
Somewhere in a Qt-forum I found the following solution that actually solves the problem exactly where it occurs without having impact on other parts.
In the first step you need to derive from QProxyStyle and overwrite the pixelMetric member function:
class CustomLineEditProxyStyle : public QProxyStyle
{
public:
virtual int pixelMetric(PixelMetric metric, const QStyleOption* option = 0, const QWidget* widget = 0) const
{
if (metric == QStyle::PM_TextCursorWidth)
return 0;
return QProxyStyle::pixelMetric(metric, option, widget);
}
};
The custom function simply handles QStyle::PM_TextCursorWidth and forwards otherwise.
In your custom LineEdit class constructor you can then use the new Style like this:
m_pCustomLineEditStyle = new CustomLineEditProxyStyle();
setStyle(m_pCustomLineEditStyle);
And don't forget to delete it in the destructor since the ownership of the style is not transferred (see documentation). You can, of course, hand the style form outside to your LineEdit instance if you wish.
Don't get complicated:
In QtDesigner ,
1.Go the the lineEdit 's property tab
2.Change focusPolicy to ClickFocus
That's it...

QTabWidget how to hide pane only?

I have added a QToolButton as corner widget in QTabWidget which is checkable. I want to hide all tabs (panes only) when the tool button is unchecked. I tried to connect button's signal clicked(bool) with all tab's setVisible(bool) slot not working but. I also connected tabwidget's setvisible to the signal but complete widget became invisible(it was a silly trial). Is there any way to make only pane invisible and tab bar will not disappear ?
Edit: Code (ui have a tabwidget and two tabs namely tab and tab_2)
ui->setupUi(this);
QToolButton * b = new QToolButton;
b->setCheckable(true);
b->setChecked(true);
b->setAutoRaise(true);
b->setText("Hide Tabs");
ui->tabWidget->setCornerWidget(b);
connect(b,SIGNAL(clicked()),ui->tab,SLOT(hide()));
connect(b,SIGNAL(clicked()),ui->tab_2,SLOT(hide()));
Use qFindChild to find the QTabBar within the QTabWidget:
QTabBar *tabBar = qFindChild<QTabBar *>(ui->tabWidget);
tabBar->hide();
For Qt5:
QTabBar *tabBar = ui->tabWidget->findChild<QTabBar *>();
tabBar->hide();
so I understand it like this, you want to hide the TabBar and let the tab visible. Or at least that's what I get from your question
Well if that the case all you have to do it's this:
connect(ui->pushButton,SIGNAL(clicked()),ui->tabWidget->tabBar(),SLOT(hide()));
I hope this was helpful, even do the questions in a little old, I though it may help new viewers.
Here is my take on this. I've created a class that inherits QTabWidget. What I do is; set the "maximum vertical size of QTabWidget" to its tabBars height to hide the panels.
It is a hacky solution and I had to add some extra lines to deal with quirks.
file: hidabletabwidget.h
#ifndef HIDABLETABWIDGET_H
#define HIDABLETABWIDGET_H
#include <QTabWidget>
#include <QAction>
class HidableTabWidget : public QTabWidget
{
Q_OBJECT
public:
explicit HidableTabWidget(QWidget *parent = 0);
QAction hideAction;
private slots:
void onHideAction(bool checked);
void onTabBarClicked();
};
#endif // HIDABLETABWIDGET_H
file: hidablewidget.cpp
#include "hidabletabwidget.h"
#include <QTabBar>
#include <QToolButton>
HidableTabWidget::HidableTabWidget(QWidget *parent) :
QTabWidget(parent),
hideAction("▾", this)
{
hideAction.setCheckable(true);
hideAction.setToolTip("Hide Panels");
QToolButton* hideButton = new QToolButton();
hideButton->setDefaultAction(&hideAction);
hideButton->setAutoRaise(true);
this->setCornerWidget(hideButton);
connect(&hideAction, SIGNAL(toggled(bool)), this, SLOT(onHideAction(bool)));
connect(this, SIGNAL(tabBarClicked(int)), this, SLOT(onTabBarClicked()));
}
void HidableTabWidget::onHideAction(bool checked)
{
if (checked)
{
this->setMaximumHeight(this->tabBar()->height());
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
}
else
{
this->setMaximumHeight(QWIDGETSIZE_MAX); // by default widgets can expand to a maximum sized defined by this macro
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}
}
void HidableTabWidget::onTabBarClicked()
{
hideAction.setChecked(false);
}
To use this, you can simply "promote" your QTabWidget to "HidableTabWidget" using qt designer.
And here is how it looks on my system:
You usually want to remove the Tab from the QTabWidget:
void QTabWidget::removeTab ( int index )
The Tab removed will not be deleted and can be reinserted!
So you would connect your QToolButton b to a slot which simply removes the Tabs like this:
connect( b, SIGNAL(clicked()), this, SLOT(hideTabs() );
..
void Foobar::hideTabs( void )
{
for( int i = 0; i < ui->tabWidget->count(); ++i )
ui->tabWidget->removeTab(i);
}
I can not comment due to my low "reputation" so far. If I could I'd just add a comment to Anatoli's answer: the goal is to hide "page area", not "tab bar". So if we imply they always use QStackedWidget for that then the answer should be more like:
auto * tab_pane = qFindChild<QStackedWidget *>(ui->tabWidget);
tab_pane->hide();
or for Qt5:
auto * tab_pane = ui->tabWidget->findChild<QStackedWidget *>();
tab_pane->hide();

How to disable the resize cursor

I use QWidget::setFixedSize to avoid my window being resized. Even though it works, the resize-style cursor still appears when passing over the edges.
Like this for example: http://bp3.blogger.com/_fhb-4UuRH50/R1ZMKyoIvMI/AAAAAAAAA6s/I08ntfXpp2k/s1600-h/w-resize.gif
Well, you know what I mean. How can I avoid that?
I use Windows 7 with the default windows manager.
If this is your mainwindow and you're using Qt 4, you can disable the sizegrip of your mainwindow's statusbar:
this->statusBar()->setSizeGripEnabled(false);
Otherwise you can set the Qt::MSWindowsFixedSizeDialogHint flag to your window:
this->setWindowFlags(this->windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
First solution
You can add the following flag to the flags of your window to prevent the window from being resized by the user:
setWindowFlags(this->windowFlags() |= Qt::FramelessWindowHint);
Here is some more information about Window Flags.
Second (ugly) experiment solution
This is kind of a dirty work-around... I'm fully aware of the fact, that this is not clean.
I just wrote this little main window that changes the cursor manually when the main window's area is left.
Note: You have to consider side effects. Maybe there is another cursor shape needed for a child widget, but this overrides the cursor for the complete application.
This can be used as a starting point for further development and for simple applications.
Header:
class CMainWindow :
public QMainWindow
{
public:
CMainWindow(QWidget* parent = nullptr);
virtual ~CMainWindow(void);
protected:
virtual void leaveEvent( QEvent *event );
virtual void enterEvent( QEvent *event );
};
cpp:
CMainWindow::CMainWindow(QWidget* parent) : QMainWindow(parent)
{
setMouseTracking(true);
}
CMainWindow::~CMainWindow(void)
{
}
void CMainWindow::leaveEvent( QEvent *event )
{
qApp->setOverrideCursor(QCursor(Qt::ArrowCursor));
QMainWindow::leaveEvent(event);
}
void CMainWindow::enterEvent( QEvent *event )
{
qApp->restoreOverrideCursor();
QMainWindow::enterEvent(event);
}
Use
setMinimumSize(QSize(width_px,height_px))
setMaximumSize(QSize(width_px,height_px))
where both methods have same size.You won't see the resize cursor & the window thus doesn't get resized/maximized.

Resources