I have a QMainWindow and wish to remember its size and position on the screen.
This I can do with saveGeometry(), to save the settings to a .ini file and restoreGeometry() - to restore the window.
However, what will be the behaviour of the Window on a multiscreen setup?
Is it possible for the Window to be launched on the correct calling window, and with its size and position on that window remembered?
In my current implementation, I have taken care of the launch of the application where the mouse pointer currently is, but the window is always full screen, unless someone sets the position manually in the ini file.
int posX = cSfcConfig::getProperties(MAIN_WINDOW, POS_X).toInt();
int posY = cSfcConfig::getProperties(MAIN_WINDOW, POS_Y).toInt();
QByteArray locationArray = cSfcConfig::getLocationSetting();
if ( posX > 0 || posY > 0)
{
QRect rect = QDesktopWidget().availableGeometry();
QDesktopWidget *m=new QDesktopWidget();
QPoint p= QCursor::pos();
int r= m->screenNumber(p);
QRect d=m->screenGeometry(r);
//QPoint l = d.();
int width = rect.width() - (posX * 2);
int height = rect.height() - posY;
//mainWindow.restoreGeometry(locationArray);
//mainWindow.restoreState(cSfcConfig::GetStateSetting());
mainWindow.setGeometry(posX, posY, width, height);
mainWindow.show();
mainWindow.move(l);
}
else
{
mainWindow.showMaximized();
}
Related
I am currently using the MoveWindow() function in the header Windows.h, and using this function, I can move and resize the output console window any way I want.
MoveWindow(GetConsoleWindow(), x, y, width, height, TRUE);
// x and y is the position of the topleft corner of window
However, I cannot figure out how to center the screen without hard-coding the position of the window. Is there a way to set the position of the window to change depending on the width and height that I set? Thanks!
P.S. I am pretty new to C++
Get the WindowRect ( not to confuse with the ClientWindow)of your screen and find middle position, but ClientRect will remain unchanged since we are not resizing.Try this snippet:
Edited: For proper centering and to allow user to specify the position
void MoveWindow(int posx, int posy)
{
RECT rectClient, rectWindow;
HWND hWnd = GetConsoleWindow();
GetClientRect(hWnd, &rectClient);
GetWindowRect(hWnd, &rectWindow);
MoveWindow(hWnd, posx, posy, rectClient.right - rectClient.left, rectClient.bottom - rectClient.top, TRUE);
}
void MoveCenter()
{
RECT rectClient, rectWindow;
HWND hWnd = GetConsoleWindow();
GetClientRect(hWnd, &rectClient);
GetWindowRect(hWnd, &rectWindow);
int posx, posy;
posx = GetSystemMetrics(SM_CXSCREEN) / 2 - (rectWindow.right - rectWindow.left) / 2,
posy = GetSystemMetrics(SM_CYSCREEN) / 2 - (rectWindow.bottom - rectWindow.top) / 2,
MoveWindow(hWnd, posx, posy, rectClient.right - rectClient.left, rectClient.bottom - rectClient.top, TRUE);
}
int main(int argc, char *argv[])
{
MoveWindow(10, 10);
return 0;
}
I'm trying to make the OF window get resized proportionally maintaining the same ratio between width and height of the window.
For example, if you created a window with 400x300 dimensions and if you stretch the width to 800, then the height will automatically be stretched to 600 even though you only stretched the window horizontally.
Anyways, in order to implement this feature, I needed to use ofSetWindowShape() inside windowResized() listener.
I could quickly prototype this on MacOS X and it worked very well.
Here's the code:
ofApp.h
enum ScaleDir { //window scaling directions
SCALE_DIR_HORIZONTAL,
SCALE_DIR_VERTICAL,
};
ScaleDir scaleDir;
int windowWidth, windowHeight; //original window dimensions
float widthScaled, heightScaled; //scaled window dimensions
float windowScale; //scale amount (1.0 = original)
bool bScaleDirFixed; //is direction fixed?
ofApp.cpp
//--------------------------------------------------------------
void ofApp::setup(){
windowWidth = ofGetWidth();
windowHeight = ofGetHeight();
windowScale = 1.0f;
widthScaled = windowWidth * windowScale;
heightScaled = windowHeight * windowScale;
}
//--------------------------------------------------------------
void ofApp::update(){
if (bScaleDirFixed) {
bScaleDirFixed = false;
}
}
//--------------------------------------------------------------
void ofApp::draw(){
ofSetColor(255, 0, 0);
ofSetCircleResolution(50);
ofDrawEllipse(widthScaled/2, heightScaled/2, widthScaled, heightScaled); //the ellipse will be scaled as the window gets resized.
}
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){
if (!bScaleDirFixed) {
int gapW = abs(widthScaled - w);
int gapH = abs(heightScaled - h);
if (gapW > gapH)
scaleDir = SCALE_DIR_HORIZONTAL;
else
scaleDir = SCALE_DIR_VERTICAL;
bScaleDirFixed = true;
}
float ratio;
if (scaleDir == SCALE_DIR_HORIZONTAL) {
ratio = static_cast<float>(windowHeight) / static_cast<float>(windowWidth);
h = w * ratio;
windowScale = static_cast<float>(w) / static_cast<float>(windowWidth);
}
else if (scaleDir == SCALE_DIR_VERTICAL) {
ratio = static_cast<float>(windowWidth) / static_cast<float>(windowHeight);
w = h * ratio;
windowScale = static_cast<float>(h) / static_cast<float>(windowHeight);
}
widthScaled = windowWidth * windowScale;
heightScaled = windowHeight * windowScale;
ofSetWindowShape(widthScaled, heightScaled);
}
However, if I run the same code on Ubuntu, the app freezes as soon as I resize the window. It seems ofSetWindowShape() calls windowResized() listener and therefore it goes into an infinite loop.
(windowResized -> ofSetWindowShape -> windowResized ->
ofSetWindowShape....)
How can I change the code so it can also work on Ubuntu without the problem?
Any advice or guidance would be greatly appreciated!
P.S: I would also appreciate if Linux users can confirm the app freezing.
Did you try:
ofSetupOpenGL(widthScaled, heightScaled, OF_WINDOW);
Apparently ofSetWindowShape() should only be called during App::Setup() ...
see OF tutorials here
I want to show a pixmap on Qt and make able to zoom, I'm using a QWidget inside a QScrollArea, but the ScrollBars of the area are not working, when I zoom on the image, the image gets bigger, but there is no scrollbars so i can move, let me show you some code :
Here is how I'm declaring the Widgets :
_scroll = new QScrollArea(_frame);
_image_widget = new QImageWidget(_scroll);
_scroll->setBackgroundRole(QPalette::Dark);
_scroll->setWidget(_image_widget);
_scroll->setWidgetResizable(true);
_frame is the area where i should show the hole thing, _image_widget is an object of QImageWidget which is inheriting from QWidget
if I dont use this : _scroll->setWidgetResizable(true); the image is just too small
And here is how I deal with the Zoom :
void QImageWidget::paintEvent(QPaintEvent *ev) {
QPainter p(this);
if(pixmap() != NULL){
int w = pixmap()->width();
int h = pixmap()->height();
QPixmap map = pixmap()->scaled(w*zoom,h*zoom,Qt::KeepAspectRatio);
p.drawPixmap(0, 0, map );
}
}
void QImageWidget::wheelEvent ( QWheelEvent * e )
{
int x = e->pos( ).x();
int y = e->pos( ).y();
if (e->delta() > 0)
zoom *= 2;
else
if(zoom > 1)
zoom /= 2;
}
SO the problem is as I said, the image keeps getting bigger when i'm zooming until it takes the hole area of the QScrollArea and then when I keep zooming, the zoom is working but there is no ScrollBars so i can see the other part of the Image.
Tell me if i'm not understandable !
thanks !
I found the answer to my question, all i had to do is add this resize(sizeHint()*zoom); before drawing the pixmap :
void QImageWidget::paintEvent(QPaintEvent *ev) {
QPainter p(this);
if(pixmap() != NULL){
int w = pixmap()->width();
int h = pixmap()->height();
QPixmap map = pixmap()->scaled(w*zoom,h*zoom,Qt::KeepAspectRatio);
resize(sizeHint()*zoom);
p.drawPixmap(0, 0, map );
}
}
the pixels were updated but not the size of the widget !
Creating a window with GLFW3 is done using glfwCreateWindow:
GLFWwindow* glfwCreateWindow ( int width,
int height,
const char *title,
GLFWmonitor *monitor,
GLFWwindow *share
)
If the monitor parameter is not NULL, the window is created in full screen mode on the given monitor. One can receive the primary monitor by calling glfwGetPrimaryMonitor, or chose one of the results of glfwGetMonitors. But how can I create a full screen window on the current monitor, i.e. the monitor the window is currently running in windowed mode? There seems to be no way to receive the currently used monitor. There is glfwGetWindowMonitor, but it only returns the monitor in full screen mode, NULL in windowed mode.
You can find the current monitor with glfwGetWindowPos/glfwGetWindowSize.
This function returns the monitor that contains the greater window area.
static int mini(int x, int y)
{
return x < y ? x : y;
}
static int maxi(int x, int y)
{
return x > y ? x : y;
}
GLFWmonitor* get_current_monitor(GLFWwindow *window)
{
int nmonitors, i;
int wx, wy, ww, wh;
int mx, my, mw, mh;
int overlap, bestoverlap;
GLFWmonitor *bestmonitor;
GLFWmonitor **monitors;
const GLFWvidmode *mode;
bestoverlap = 0;
bestmonitor = NULL;
glfwGetWindowPos(window, &wx, &wy);
glfwGetWindowSize(window, &ww, &wh);
monitors = glfwGetMonitors(&nmonitors);
for (i = 0; i < nmonitors; i++) {
mode = glfwGetVideoMode(monitors[i]);
glfwGetMonitorPos(monitors[i], &mx, &my);
mw = mode->width;
mh = mode->height;
overlap =
maxi(0, mini(wx + ww, mx + mw) - maxi(wx, mx)) *
maxi(0, mini(wy + wh, my + mh) - maxi(wy, my));
if (bestoverlap < overlap) {
bestoverlap = overlap;
bestmonitor = monitors[i];
}
}
return bestmonitor;
}
After discussion on IRC it seems that it is not possible to retrieve the currently active monitor (as in the monitor the window is currently drawn on) with GLFW. Therefore it is not possible to create a full screen window on the current monitor.
EDIT: Even though there is no GLFW functionality to directly achieve this, the answer of Shmo provides an elegant solution.
Here is Shmo's answer, ported over to LWJGL:
/** Determines the current monitor that the specified window is being displayed on.
* If the monitor could not be determined, the primary monitor will be returned.
*
* #param window The window to query
* #return The current monitor on which the window is being displayed, or the primary monitor if one could not be determined
* #author Shmo<br>
* Ported to LWJGL by Brian_Entei */
#NativeType("GLFWmonitor *")
public static final long glfwGetCurrentMonitor(long window) {
int[] wx = {0}, wy = {0}, ww = {0}, wh = {0};
int[] mx = {0}, my = {0}, mw = {0}, mh = {0};
int overlap, bestoverlap;
long bestmonitor;
PointerBuffer monitors;
GLFWVidMode mode;
bestoverlap = 0;
bestmonitor = glfwGetPrimaryMonitor();// (You could set this back to NULL, but I'd rather be guaranteed to get a valid monitor);
glfwGetWindowPos(window, wx, wy);
glfwGetWindowSize(window, ww, wh);
monitors = glfwGetMonitors();
while(monitors.hasRemaining()) {
long monitor = monitors.get();
mode = glfwGetVideoMode(monitor);
glfwGetMonitorPos(monitor, mx, my);
mw[0] = mode.width();
mh[0] = mode.height();
overlap =
Math.max(0, Math.min(wx[0] + ww[0], mx[0] + mw[0]) - Math.max(wx[0], mx[0])) *
Math.max(0, Math.min(wy[0] + wh[0], my[0] + mh[0]) - Math.max(wy[0], my[0]));
if (bestoverlap < overlap) {
bestoverlap = overlap;
bestmonitor = monitor;
}
}
return bestmonitor;
}
This code is working :
QRect r = QApplication::desktop()->availableGeometry();
QRect main_rect = this->geometry();
main_rect.moveTopRight(r.topRight());
this->move(main_rect.topLeft());
This code is working on position of screen.. But I want to align to the right of screen..
Do you have any idea ?
Thank you..
I think you should use setAlignment to your main layout something like this
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->setAlignment(Qt::AlignRight);
I have a solution, but sadly it's not that easy...
First, you have to do the movement after a short delay, you can read more about it here (Check the accepted answere)
And what you have to do to move the window is the following:
void MainWindow::timerEvent(QTimerEvent *event)
{
if(event->timerId() == this->TimerID)
{
event->accept();
this->killTimer(this->TimerID);
//Used to kill the timer that was created in the constructor, needs the ID to do this
QRect desktopGeom = QApplication::desktop()->availableGeometry(); //Screen size
QRect windowFrame = this->frameGeometry(); //Window with frame
QRect windowSize = this->geometry(); //Window without frame
int smallFrameFactor = (windowFrame.width() - windowSize.width()) / 2; //Because the left, right and bottom border have the same size
int wideFrameFactor = windowFrame.height() - (windowSize.height() + smallFrameFactor); //The big, upper border
int x_pos = desktopGeom.x() + desktopGeom.width() - windowSize.width() - smallFrameFactor;
int y_pos = desktopGeom.y() + wideFrameFactor;
this->setGeometry(x_pos, y_pos, windowSize.width(), windowSize.height());
}
else
event->ignore();
}
I added a picture, to vizualize what I did above. I hope I was able to help you.
EDIT: Just saw this question is over a year old... By maybe it's still helpful for someone...