- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我有一个带有通知区域图标的应用程序,因此主窗口可能会忽略关闭事件。我正在尝试在应用程序退出时保存首选项和历史记录。我还想在应用程序运行时处理注销。虽然该应用程序是跨平台的,但它在 GNU/Linux 中最为方便/有用,因此 Windows 的注销行为无关紧要。这是一个最小的可编译示例,用于测试不同桌面环境/窗口管理器的行为:
// main.cpp
# include <QApplication>
# include <QMainWindow>
# include <QCloseEvent>
# include <QTimer>
# include <iostream>
class M : public QMainWindow
{
Q_OBJECT
public:
~M();
public slots:
void onAboutToQuit();
private:
void closeEvent(QCloseEvent *);
};
M::~M()
{
std::cout << "M::~M()" << std::endl;
}
void M::onAboutToQuit()
{
std::cout << "onAboutToQuit()" << std::endl;
}
void M::closeEvent(QCloseEvent * e)
{
std::cout << "closeEvent()" << std::endl;
hide();
QTimer::singleShot(5000, this, SLOT(show()));
e->ignore();
}
int main(int argc, char * argv[])
{
QApplication app(argc, argv);
M m;
m.setWindowModality(Qt::NonModal);
m.connect(& app, SIGNAL(aboutToQuit()),
SLOT(onAboutToQuit()));
m.show();
return app.exec();
}
# include "main.moc"
// CMakeLists.txt
cmake_minimum_required(VERSION 2.6)
project(closeeventbug)
option(QT5 "Use Qt5" OFF)
if(QT5)
find_package(Qt5Core REQUIRED)
find_package(Qt5Widgets REQUIRED)
else()
find_package(Qt4 REQUIRED)
include_directories(${QT_INCLUDES})
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_AUTOMOC ON)
add_executable(closeeventbug main.cpp)
if(QT5)
qt5_use_modules(closeeventbug Core Widgets)
else()
target_link_libraries(closeeventbug ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY})
endif()
大多数成熟的桌面环境在注销时会尝试关闭可见窗口。但是由于测试应用程序在关闭时不会退出,因此注销会被中断/取消。如果在窗口不可见时执行注销,它会优雅地退出(就像我想要的那样)。功能较少的桌面环境/窗口管理器会忽略仍在运行的应用程序并退出。它们中的大多数甚至不警告应用程序注销,因此程序输出到的文件中既没有“closeEvent()”,也没有“onAboutToQuit()”,也没有“M::~M()”被重定向。
详细结果(所有非Windows结果均来自Manjaro GNU/Linux):
成熟的桌面环境,如果可见窗口拒绝退出,则取消注销,优雅地完成不可见的应用程序:
closeEvent()
onAboutToQuit()
M::~M()
{ KDE, XFCE, Mate, GNOME, Cinnamon }
所有其他人都没有取消退出,但其中一些人试图警告应用程序。
我不知道为什么 onAboutToQuit() 会出现在日志中,但 M::~M() 不在这种情况下...
closeEvent()
onAboutToQuit()
{ Windows7 }
3.
closeEvent()
{ icewm, E17 }
4.
<nothing in the log>
{ RazorQt, LxDE, LxQt, i3, budgie, fluxbox, awesome, openbox,
wmii, E16, pekWM, uwm, fvwm, xmonad, spectrwm, windowmaker,
herbstluftwm, WindowsXP }
对于(GCC 4.9.1 或 Clang 3.4.2)和(Qt 4.8.6 或 Qt 5.3.1)的任意组合,行为完全相同。然而,当我在 Xubuntu 上尝试 Qt 4.8 和 Qt 5.2 时,结果有些不同:XFCE 中的 Qt 5.2 没有阻塞——无论主窗口可见性如何,应用程序都能正常完成。但是 Qt 4.8 中存在阻塞(与 Manjaro 中一样)。
我知道可以正确处理注销(不阻塞),因为有几个应用程序可以很好地做到这一点。它们都有通知区域图标,关闭通知区域,但不阻止注销。
我检查了基于 Qt 的源代码,发现在处理 closeEvent 方面没有什么特别之处:
https://github.com/goldendict/goldendict/blob/master/mainwindow.cc
void MainWindow::closeEvent( QCloseEvent * ev )
{
if ( cfg.preferences.enableTrayIcon && cfg.preferences.closeToTray )
{
ev->ignore();
hide();
}
else
{
ev->accept();
qApp->quit();
}
}
https://github.com/bfleischer/transmission/blob/master/qt/mainwin.cc
void
TrMainWindow :: closeEvent( QCloseEvent * event )
{
// if they're using a tray icon, close to the tray
// instead of exiting
if( !myPrefs.getBool( Prefs :: SHOW_TRAY_ICON ) )
event->accept( );
else {
toggleWindows( false );
event->ignore( );
}
}
void
TrMainWindow :: toggleWindows( bool doShow )
{
if( !doShow )
{
hide( );
}
else
{
if ( !isVisible( ) ) show( );
if ( isMinimized( ) ) showNormal( );
//activateWindow( );
raise( );
QApplication::setActiveWindow( this );
}
}
git clone git://anongit.kde.org/kopete
void KopeteWindow::closeEvent ( QCloseEvent *e )
{
// if we are not ok to exit on close and we are not shutting down then just do what needs to be done if a
// window is closed.
KopeteApplication *app = static_cast<KopeteApplication *> ( kapp );
if ( !shouldExitOnClose() && !app->isShuttingDown() && !app->sessionSaving() ) {
// BEGIN of code borrowed from KMainWindow::closeEvent
// Save settings if auto-save is enabled, and settings have changed
if ( settingsDirty() && autoSaveSettings() )
saveAutoSaveSettings();
if ( queryClose() ) {
e->accept();
}
// END of code borrowed from KMainWindow::closeEvent
kDebug ( 14000 ) << "just closing because we have a system tray icon";
}
else
{
kDebug ( 14000 ) << "delegating to KXmlGuiWindow::closeEvent()";
KXmlGuiWindow::closeEvent ( e );
}
}
所以问题:
即使主窗口可见,如何确保我的应用程序不会阻止注销?
如何确保在尽可能多的桌面环境/窗口管理器中注销时调用 onAboutToQuit() 和 ~M()?
我怀疑应该听一些系统信号,但我不知道到底是哪个...
最佳答案
QApplication 有 signal与操作系统 session 操作相关 - 您可以轻松处理它。有关详细信息,请查看 Qt 文档 Session Management页面
关于c++ - 如何在注销时优雅地退出 QApplication?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25108520/
我目前正在为 Cocoa/Objective-C 项目编写一个脚本来完全自动化我的编译-运行-调试过程。 我的最后一行代码是: lldb -f Build/MyApp.app -o "run" 这实际
我有一个带有登录屏幕的脚本,如果按下取消按钮,我想完全退出该应用程序。我尝试了 3 种方法: 系统退出() QApplication.quit() QCoreApplication.instance(
我有一个 Flash 应用程序,可以重定向到另一个页面。我很乐意捕获任何其他窗口卸载事件(单击链接/提交表单)并警告用户他们将丢失 Flash 应用程序中的进度。 但是,我找不到任何方法来判断 URL
我正在尝试在 Ubuntu 上用 Python 编写一个简单的程序,它将在播放视频完成后关闭/退出/退出 VLC Player。 能否请您指导我应该在我的程序中添加什么以获得我需要的结果。 impor
我在 Lynda.com 上学习 PHP 2 视频时遇到了一个问题,因为讲师似乎忽略了告诉我们他在视频中执行的步骤之一。我在这里上传了相关视频http://www.youtube.com/watch?
某天在群内有同学问到,在python下我用input或者raw_input都得输入完后回车才能获取到输入的值,那如何实现任意键退出暂停等功能呢,我当时也没有多想,因为接触python时间也不算长,主
我按顺序调用了几个函数(我无法编辑),但有些函数会重定向用户,所以我永远不会进入下一个函数。 我正在调用一个第三方函数,它调用了我能够阻止的 wp_redirect(),但是下一行是 exit;我不知
终止/退出主函数的 D 方式是什么? import std.stdio; import core.thread; void main() { int i; while (i <= 5)
我正在申请写作。用户可以打开应用程序、写一些文本、保存他们的工作等。 我试图做到这一点,以便点击 window close按钮将提示用户 (a) 保存他们的工作(如有必要)或 (b) 退出。 我正在尝
我正在通过在 repl 中检查别人的代码来玩弄它。 它不断调用 System/exit,这导致我的 repl 崩溃。这真是令人气愤。 在我有权访问的所有代码中,我都模拟了调用。 但它也会调用一些我没有
我正在使用 subprocess执行mimic的模块程序(指定 here )。下面的代码成功地读取了一些文本并写入了一个 mp3 文件。 import subprocess proc = subpro
退出 .then 范围后数组上的值被清除 在下面的代码中tableValues1.length 给我正确的长度,直到它位于每个循环内当它退出时,作用域数组长度为零。 请谁能帮我解决这个问题 - 谢谢
我正在尝试为 s3cmd 编写一个 docker 镜像。当我通过 docker-compose 运行从 Dockerfile 构建的图像时,容器在 docker compose run 命令之前退出。
这个问题已经有答案了: 已关闭12 年前。 Possible Duplicate: Quitting an application - is that frowned upon? 我编写了一个 And
我遇到 Selenium WebDriver 仅执行一次后退出 for 循环的问题。据推测,这是获取内容和在加载页面之前启动循环的问题。是否有可能让 webdriver 等待页面加载? List al
#include #include #include #include "Player.h" using namespace std; void PlayerMenu(); int main()
class Test{ public static void main(String args[]) { Patron list[] = new PatronData(
我正在做一些作业,遇到了这个问题。 Write a program that reads several lines of text and prints a table indicating the
我正在用 C 创建一个简单的 Linux 命令 shell。我无法理解我的代码在哪里出现问题。 “commands”是我希望作为一个父进程的子进程同时执行的 Linux 命令字符串列表。当所有执行完成
我的控制台应用程序有点问题。应用程序应该从用户那里获取数字并将它们添加到列表中,但是如果输入是“c”,它应该关闭。我不知道如何在不使用 Scanner.nextLine() 挂起应用程序并退出循环的情
我是一名优秀的程序员,十分优秀!