I have a QWidget as the child of another within my application. The task consists of putting the internal widget in full screen mode and being able to see it again in normal mode with the same button. This partly I have managed to do it in the following way:
if(!isFullScreen())
{
setWindowFlags(windowFlags() | Qt::Window);
showFullScreen();
}
else
{
setWindowFlags(windowFlags() & ~Qt::Window);
showNormal();
activateWindow();
}
The problem arises when you return to see the widget in normal mode. Things that happen:
The mouse cursor stays with pointing hand cursor.
The button to change mode remains in hover state (the background color is changed when the mouse is over)
Passing the mouse through other widget controls does not change its appearance
I have to click on the widget to fix the behavior. It's as if the widget did not receive events of any kind or something like that. I tried calling setFocus () and it did not work. I have also tried to send an event by hand in the following way but it has not worked either:
QMouseEvent my_event(QEvent::MouseButtonPress, QPointF (0, 0), Qt :: NoButton, 0, 0);
QApplication::sendEvent(this, & my_event);
Any ideas?
Thanks.
Cannot reproduce your issue on Xubuntu with Qt5.9.4.
However I did the same in my last job, and it worked correctly on all platforms. It was something like this, I think:
if(!isFullScreen())
{
setParent(0);
showFullScreen();
}
else
{
orignalParentLayout->addWidget(this); // better: insert at correct position
showNormal();
}
For this you have to add some knowledge about the parent's layout though. You could try to detect that info before going into full screen mode, but it is probably not worth the effort.
You could also try:
if(!isFullScreen())
{
logicalParent = parentWidget();
setParent(0);
showFullScreen();
}
else
{
setParent(logicalParent);
showNormal();
}
If you have no layout. You might also want to store the geometry before going to full screen.
Related
I meet two problems, I searched, but they seems not so easy as I think.
I'm working on ubuntu-18.04 with qt-5.15.x. And my two problems are:
cannot restore my window after maximizing it.
cannot move my window out of my screen with mouse dragging
Can not restore
Firstly, I set my window frameless, and then using a button standing for maximize or restoreoperations to trigger maximization or normal
// set fremeless in contruction
setWindowFlags(Qt::FramelessWindowHint | windowFlags());
// maximaization slot or restore
void WindowTitle::onButtonMaxClicked()
{
QWidget *pWin = window();
if(pWin->isMaximized())
{
pWin->showNormal();
}
else
{
pWin->showMaximized();
}
}
What I expected is when I click button ,window will maximized, and that is true indeed. Then clicking on button again, window will return original position and size again, but that doesn't happen, instead, window's height is correct, but its width is equal screen(getting rid of applications docker bar), x-axis value is wrong too. And I have tried setGeometry after I have stored its value, but failed.
Can not move outside
I can make sure that I have set correct position with
void WindowTitle::mouseMoveEvent(QMouseEvent *event)
{
if (m_isPressed)
{
QPoint movePoint = event->globalPos() - m_startMovePos;
QPoint widgetPos = QApplication::activeWindow()->pos();
m_startMovePos = event->globalPos();
QApplication::activeWindow()->move(widgetPos.x() + movePoint.x(), widgetPos.y() + movePoint.y());
}
return QWidget::mouseMoveEvent(event);
}
function, but the result shows something wrong.
I have searched above two questions. But get nothing. And I'm curious that other applications can do just right both restore and move, suchlike Firefox web browser(which I'm typing on). So, there must be some way to make it work.
I'm trying to implement a TinyMCE button that will apply the style of the selection to the entire box. I'm having trouble, though, reading the style of the selection when the selection is buried in a span in a span in a paragraph. Let's consider 'color' for example. Below I have a box with some text and I've selected "here" in the paragraph and made it red.
The HTML for the paragraph is now:
The code behind my button to apply the style of the selection to the box is
var selected_color = $(ed.selection.getNode()).css('color');
console.log("color pulled is ", selected_color);
$(ed.bodyElement).css('color', selected_color);
It doesn't work because the color pulled is black, not red, so the third line just re-applies the black that's already there. (If I replace selected_color in the third line with 'blue' everything goes blue.) So the problem is pulling the color of the current selection.
Does anyone know how I can do this reliably, no matter how buried the selection is?
Thanks for any help.
I also noticed somewhat a strange behavior up and there, with selections of nested span's and div's, but honestly i'm not able to recognize if this is a bug of TinyMCE, a browser issue or a combination of both (most probably).
So, waiting for some more information from you (maybe also your plugin code) in the meanwhile i realized two proposal to achieve what you want: the first plugin behaves like the format painter in word, the second is simply applying the current detected foreground color to the whole paragraph.
As you move throug the editor with the keyboard or mouse, you will see the current detected foreground color highlighted and applied as background to the second plugin button.
Key point here are two functions to get the styles back from the cursor position:
function findStyle(el, attr) {
var styles, style, color;
try {
styles = $(el).attr('style');
if(typeof styles !== typeof undefined && styles !== false) {
styles.split(";").forEach(function(e) {
style = e.split(":");
if($.trim(style[0]) === attr) {
color = $(el).css(attr);
}
});
}
} catch (err) {}
return color;
}
function findForeColor(node) {
var $el = $(node), color;
while ($el.prop("tagName").toUpperCase() != "BODY") {
color = findStyle($el, "color");
if (color) break;
$el = $el.parent();
}
return color;
}
The try...catch block is needed to avoid some occasional errors when a selected text is restyled. If you look at the TinyMCE sorce code you will notice a plenty of timing events, this is a unavoidable and common practice when dealing with styles and css, even more with user interaction. There was a great job done by the authors of TinyMCE to make the editor cross-browser.
You can try out the first plugin in the Fiddle below. The second plugin is simpler as the first one. lastForeColor is determined in ed.on('NodeChange'), so the code in button click is very easy.
tinymce.PluginManager.add('example2', function(ed, url) {
// Add a button that opens a window
ed.addButton('example2', {
text: '',
icon: "apply-forecolor",
onclick: function() {
if(lastForeColor) {
var applyColor = lastForeColor;
ed.execCommand('SelectAll');
ed.fire('SelectionChange');
ed.execCommand('forecolor', false, applyColor);
ed.selection.collapse(false);
ed.fire('SelectionChange');
}
return false;
}
});
});
Moreover: i think there is a potential issue with your piece of code here:
$(ed.bodyElement).css('color', selected_color);
i guess the style should be applied in a different way, so in my example i'm using standard TinyMCE commands to apply the foreground color to all, as i wasn't able to exactly convert your screenshot to code. Please share your thoughts in a comment.
Fiddle with both plugins: https://jsfiddle.net/ufp0Lvow/
deblocker,
Amazing work! Thank you!
Your jsfiddle did the trick. I replaced the HTML with what was in my example and changed the selector in tinymce.init from a textarea to a div and it pulls the color out perfectly from my example. The modified jsfiddle is at https://jsfiddle.net/79r3vkyq/3/ . I'll be studying and learning from your code for a long time.
Regarding your question about
$(ed.bodyElement).css('color', selected_color);
the divs I attach tinymce to all have ids and the one the editor is currently attached to is reported in ed.bodyElement. I haven't had any trouble using this but I have no problem using your
ed.execCommand('SelectAll');
ed.fire('SelectionChange');
ed.execCommand('forecolor', false, applyColor);
Thanks again! Great job!
I am using the following code to switch between full screen and maximized window,
void MainWindow::keyPressEvent(QKeyEvent *e)
{
if ((e->key()==Qt::Key_Enter) && (e->modifiers()==Qt::AltModifier))
this->setWindowState(Qt::WindowFullScreen);
if (e->key()==Qt::Key_Escape)
if(isFullScreen())
this->setWindowState(Qt::WindowMaximized);
}
but this doesn't work.Can anybudy tell me what's the problem here??
You shouldn't use:
e->modifiers()==Qt::AltModifier
to check key modifiers because the modifiers() function returns flags.
Use something like:
e->modifiers()&Qt::AltModifier
or
(e->modifiers()&Qt::AltModifier)==Qt::AltModifier
Perhaps you should not use Alt+Enter.
You can change your key to Alt+F or other 'cause Alt+Enter actiually doesn't work.
I am trying to capture a screenshot of my application within the application. Its a Qt-based application. Is anyone aware of how to do this? Any suggestions are very welcome.
CV
You can tell any QWidget (including your QMainWindow) to render itself off-screen:
http://developer.qt.nokia.com/doc/qt-4.8/qwidget.html#render
Technically this is not a screenshot as it renders the widget explicitely for this purpose instead of capturing what is seen on-screen. For almost any purpose it doesn't matter.
If you have a GL widget, you can/must instead use grabFramebuffer() which has the advantage of capturing what is seen on the screen.
With this example you could get all your widget screen.
You could attach this method to any key press or signal, as you prefer, to get successive screenshot.
MyClass::screenshot()
{
QWidget *w = QApplication::activeWindow();
if(w) {
static int count = 0;
QPixmap p = QPixmap::grabWidget(w);
p.save(QString("/your/path/screenshot%1.png").arg(count));
count++;
}
}
QPixmap lets you do a window grab if you have the ID. My references are for PyQt but I'm sure you can make the adjustments:
How to get RGB values of QPixmap or QImage pixel - Qt, PyQt
http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qpixmap.html#grabWindow
In modern QT 5+ it can be done like that:
void MainWindow::takeScreenshot(const QString screenshotFileName)
{
if(isActiveWindow())
{
auto grabbedScreenshot = QWidget::grab();
grabbedScreenshot.save(screenshotFileName);
}
}
I am subclassing QTabWidget to add a QTabBar, who's tabs stretch over the whole width of the tabBar. Therefore I am setting the expanding property to true. This doesn't seem to change anything about the behavior of the tabs.
Did anyone encounter the same problem? I use Qt 4.6 in combination with
TabWidget::TabWidget(QWidget *parent)
{
tabBar = new QTabBar(this);
tabBar->setIconSize(QSize(160,160));
tabBar->setExpanding(true);
setTabBar(tabBar);
}
EDIT: has been solved, here is how I implemented it, in case anyone is interested:
tabBar = new QTabBar(this);
tabBar->setExpanding(true);
layout = new QVBoxLayout(this);
setLayout(layout);
stackedLayout = new QStackedLayout();
layout->addWidget(tabBar);
layout->addLayout(stackedLayout);
connect(tabBar, SIGNAL(currentChanged(int)), stackedLayout, SLOT(setCurrentIndex(int)));
void MainWindow::addTab(QWidget *widget, const QIcon &icon, const QString &label) {
tabBar->addTab(icon, label);
stackedLayout->addWidget(widget);
}
From the QTabBar source code:
// ... Since we don't set
// a maximum size, tabs will EXPAND to fill up the empty space.
// Since tab widget is rather *ahem* strict about keeping the geometry of the
// tab bar to its absolute minimum, this won't bleed through, but will show up
// if you use tab bar on its own (a.k.a. not a bug, but a feature).
To get around this "feature", you can create your own tab widget using a QTabBar above a widget with a QStackedLayout.
5.2.0 onwards
QTabWidget::tab-bar {
min-width: 999999px;
}
It will work. No need to use any combination. You can use QTabWidget. Daniel ans is correct.
Building on #baysmith's answer, an easier way to force the QTabWidget to let the QTabBar expand, is to set a stylesheet on your QTabWidget that looks something like this:
QTabWidget::tab-bar {
width: 999999px;
}
Or another ridiculously large number. If your QTabWidget has the tabs going vertically instead of horizontally, use 'height' instead:
QTabWidget::tab-bar {
height: 999999px;
}
This seems to work fine for me, with Qt 5.0.1. The tabs expand to fill the space, each getting an equal portion. However, it seems like they intentionally leave enough empty space for one more tab, regardless. But the rest of the space is filled as desired. The empty space might be reserved for the tear/scroll buttons, incase too many tabs get added - but I'm not sure.