销户c语言,c – 如何在注销时优雅地退出QApplication?

我有一个带有通知区域图标的应用程序,因此主窗口可能会忽略关闭事件.我正在尝试保存应用程序退出的首选项和历史记录.我还想在应用程序运行时处理注销.虽然应用程序是跨平台的,但它在GNU /

Linux中最方便/最有用,因此Windows注销行为的关注度要低得多.

这是一个用于测试不同桌面环境/窗口管理器行为的最小可编译示例:

// main.cpp

# include

# include

# include

# include

# include

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.

{ 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)AND(Qt 4.8.6 OR Qt 5.3.1)的任何组合,行为完全相同.然而,当我在Xubuntu上尝试Qt 4.8和Qt 5.2时,结果有些不同:XFCE中的Qt 5.2没有阻塞 – 无论主窗口可见性如何,应用程序都能正常完成.但Qt 4.8存在阻塞(与Manjaro相同).

我知道可以正确处理注销(没有阻塞),因为有几个应用程序可以做到这一点.所有这些都有通知区域图标,关闭通知区域,但不阻止注销.

>基于Qt:GoldenDict,Transmission-Qt,Kopete;

>以GTK为基础:Audacious,Pidgin.

我检查了基于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 ( 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()?

我怀疑应该收听一些系统信号,但我不知道究竟是哪一个……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值