如何为一个大型跨平台的C++项目编写GUI界面?

22

我有一个跨平台的C++项目(Linux和Windows),想要创建一个GUI界面。

针对这个项目,我有几个关于GUI基本原理的问题:

  1. GUI应该与应用程序逻辑分离吗?
  2. 如果它们是分离的,那么逻辑和GUI应该如何通信?TCP/IP套接字是一个好选择吗?还有其他可能性吗?
  3. 使用不同于C ++的语言编写GUI是否是个好主意?如果是,那么使用哪种语言?
  4. 使用基于浏览器的GUI是否是个好主意?
  5. 尽管项目的核心逻辑是跨平台的,但我可以决定GUI仅基于Windows (.NET?),并通过Socket或类似方法与相关Win/Linux机器上的逻辑进行通信。这样做是个好主意吗?

12
你考虑过使用Qt吗?http://qt.nokia.com/products - JRL
是的,我已经研究了Qt。这是其中之一的选择。 - Igor
12
尽管一些人无疑会试图回答你的问题,但实际上每一个问题的真正答案都是“视情况而定”。这些决策是应用架构的一部分,应由你或相关建筑师进行。你提供的只是大厦的一个钥匙孔视角,并要求结构建造建议,缺乏全貌,建议无疑会主观和不准确。我建议返回应用程序设计,寻找你所遇到的问题的解决方案,而不是从解决方案开始倒推。 - Lazarus
Mono也是一个选择。它是否成熟稳定?你认为它最适合我的需求吗? - Igor
1
@Igor,对于每个问题,你需要问自己/赞助商/关键利益相关者:“这对应用程序的实施和运营是否必要?”这是第一个依据。请记住,通常还需要考虑未来的因素,即单块应用程序现在可能符合您的要求,但未来可能不再适用。这里提供的信息不足以做出决策,如果有足够的信息,则需要比问答网站提供的更多帮助。可以阅读有关软件架构的所有内容或聘请架构师。就目前而言,“这取决于情况”就是每个问题的全部回答。 - Lazarus
显示剩余6条评论
11个回答

26
  1. 是否应该将GUI与应用程序的逻辑分开?

    是的,绝对应该这样做。

  2. 如果分离,逻辑和GUI应如何通信?TCP/IP套接字是否是一个好选择?还有其他可能性吗?

    但不要过度。套接字会使事情变得复杂(除非请参考问题5)。通常,您需要将GUI和后端部分分离为不同的类。然后,GUI类可以调用后端的方法。

  3. 在语言上与C++不同的GUI是否是一个好主意?如果是,哪种语言是最好的选择?

    如果这样做,您需要集成两种语言,因此我建议使用相同的语言编写所有内容。但是回答您的问题,例如,您可以为后端创建Python绑定,并使用PyGTK、PyQT或wxWidgets编写GUI。

  4. 是否有在基于浏览器的GUI中的好主意?

    这取决于您想如何部署应用程序。如果它应该安装在每台客户端计算机上,则Web界面没有意义。如果要集中托管它,则可以选择Web界面。

  5. 即使项目的核心逻辑是跨平台的,我也可以决定GUI仅基于Windows(.NET),并通过Socket或类似方法与相关的Win/Linux机器上的逻辑通信。这样做是否明智?

    我认为只有在后端必须是某种安全性(即不得安装在用户计算机上)或者像问题4中那样采用轻客户端方法时,才有意义。编写跨平台GUI比编写跨平台后端容易得多(在我看来),因此您应该尽量将两部分都设计成跨平台。顺便说一下,基于.NET的GUI不仅限于Windows——Mono已经支持了很多Windows Forms的子集,但不幸的是不支持WPF。

编辑:

关于您的Mono问题:Mono大多数情况下都是稳定的,但并不是所有功能都已实现。为确保,您可以运行Mono迁移分析器(MoMA)以查明在Mono中是否存在无法工作的内容。但我认为,许多公司在生产环境中成功使用Mono的事实意味着您至少应该考虑Mono作为一种选择!


9
我喜欢你的回答,但我完全不同意:“编写跨平台GUI比编写跨平台后端容易得多”。我会完全相反的说。如果你编写纯C++代码(好吧,很乐观),那么可移植性问题非常少。但是,使丰富、现代化的GUI保持一致并同时满足可移植性和本地操作系统用户体验可能是一个真正的挑战 - 有时这是一个原则上的矛盾。 - RED SOFT ADAIR
1
当他说这话时,我认为他假定会使用跨平台GUI库(例如Qt)。由于库开发人员已经处理了代码的特定于平台的部分,创建跨平台GUI有时比创建跨平台后端更容易(后者可能需要进行一些特定于平台的函数调用)。 - bta
关于.NET - 我听说有一种方法可以将任何.NET GUI导出到浏览器。你熟悉这个吗?它是.NET技术的本地部分,还是某个外部工具? - Igor
1
@Igor Oks:WPF(.net 3.0引入的新“Win Forms”技术)能够在桌面或浏览器中运行的范围非常狭窄,即使是这样,您也必须专门设计您的UI,以便在浏览器中运行时它会有意义(请搜索XBAP以获取更多信息),因此您最终得到一个看起来像浏览器UI的桌面UI。对于“任何.NET GUI”来说,这显然是不正确的,抱歉啊伙计。 - Binary Worrier
@RED SOFT ADAIR:我真的是认真的,就像 bta 已经说过的那样。鉴于已经存在稳定的跨平台 GUI 库,如 Qt、wxWidgets 和 GTK+,移植用户界面非常容易,因为代码通常是相同的(或者像 Glade 一样是 XML 文件)。在我的回答中,我将其与编写操作系统无关的后端进行了比较,在这种情况下,您必须自己编写所有可移植的代码。 - AndiDog

2
GUI应该与应用程序逻辑分离,因为UI小部件只是对象类型之一,而面向对象的规则之一是每个对象都应该信任它能够完成的责任。例如,对于序列化,对话框并不知道太多信息。
如果分离,逻辑和GUI如何通信?TCP / IP套接字是一个不错的选择吗?还有其他可能性?
这取决于您需要多少分离。我使用异步消息进行通信,然后可以使用不同的传输层而不需要进行许多更改。TCP / IP将允许您在核心和GUI分开的计算机上使用GUI,但它的开销比传递窗口消息要高。
将GUI放在与C ++不同的语言中是否是一个好主意?如果是,那么应该使用哪种语言?
理想情况下,除非您确实需要某种语言的技术能力,否则应尽可能少地使用语言。GUI更多是库问题而不是语言问题,因此,如果您可以找到非常好的C ++ UI库(提示:Qt),则应该在C ++中编写所有程序。
在基于浏览器的GUI中是否是一个好主意?
这可能是一个好主意,但您应该考虑需求而不是想法。您的客户是否希望从浏览器与您的程序交互?他们能否负担得起额外的成本和开发时间?您是否具备相应的专业知识?
即使项目的核心逻辑是跨平台的,我可以决定GUI仅基于Windows(.NET),并通过Socket或类似方法与相关Win / Linux机器上的逻辑进行通信。这样做是个好主意吗?
这可能是一个好主意,但请参见问题3的答案。还要考虑到你将要开发一个客户端 - 服务器程序,这比独立程序要复杂得多。最后,您需要评估使用.NET依赖项而不是使用C ++ UI库的优缺点:.NET带给您的东西,您无法通过wxWidgets、Qt、gtkmm等获得。

2

(1) 通常情况下,将业务逻辑和用户界面分开是有可能的。这样可以使您随时拥有基于浏览器的SaaS用户界面以及桌面式本地无网络操作模式,并共享整个应用程序逻辑代码。

(2) 不使用TCP/IP套接字。通常,应用程序和GUI会使用事件和/或消息传递进行通信。例如,当应用程序想要通知GUI发生某事时,它会创建一个合成事件,然后将其推送到GUI的事件队列中。如果应用程序也是基于事件的,则GUI可以通过发布事件与其通信。对于非阻塞、快速操作,GUI可以直接调用应用程序逻辑代码,但必须保证调用能够迅速返回。对于较慢的操作,您需要一个单独的线程来处理它们。此线程可以是处理应用程序端事件的线程,或者在需要时可以将其作为工作线程生成。

我们公司的产品在Eclipse IDE上具有用户界面,但应用程序逻辑的一部分是用C++编写的。这两个部分通过CORBA进行通信,即基本的异步事件机制。我们对这个解决方案感到满意。

在较小的规模上,GUI应用程序通常使用抽象(如Model-View-Controller(MVC))来分离UI和应用程序逻辑。

(3) 将两个不同组件编写的组件集成起来总是很麻烦的。我认为只有在您有明显的平台优势时才应该这样做。例如,我们从Eclipse IDE组件中受益,而应用程序则从C++的原始速度中受益。

(4) 基于浏览器的GUI很棒,但与业务逻辑的集成会受到延迟的影响,而Web服务器的无状态模式使架构在实际上桌面式应用程序时变得笨重。基于浏览器的GUI非常适用于软件即服务应用程序,因为它们不需要用户安装,并且可以由产品开发人员随意升级,但如果您不打算将产品作为软件即服务产品(如Salesforce),则不适用。

(5) 如果您的应用程序逻辑是跨平台的,则应尽力使UI也跨平台。否则,在那些仅支持应用程序逻辑的平台上,您可能需要安装两个操作系统,一个用于运行UI,另一个用于运行应用程序逻辑。至少有以下几种良好的跨平台用户界面框架:

  • AJAX/基于浏览器的UI
  • Trolltech / Nokia Qt
  • Eclipse(SWT)
  • Java Swing(嗯...)

关于事件和/或消息传递:它是这类项目的常见解决方案,还是比TCP/IP套接字更少使用?它有什么好处? - Igor
关于跨平台GUI,你没有提到.NET(通过MONO)。为什么它不是一个选项? - Igor
@Igor,我没有听到关于MONO <-> Windows .NET实际兼容性的好消息,但也许它可以工作。 - Antti Huima

1

一些用户已经给出了一些好的答案来回答你的问题,这就是为什么我想给你一些关于如何处理我的项目的建议。

问:我的应用程序应该在哪个操作系统上运行?

Windows和Linux!-> 我会使用C++或Java

问:运行时速度重要吗?

是的!(计算、绘图、访问系统资源...)-> 就速度而言,C++通常更快(并非总是如此)

问:需要配置文件吗?

是的!我必须设置一些用户和系统特定的值。-> 可以将配置保存到注册表中,但由于我们还想在Linux上使用我们的应用程序,所以让我们使用xml(rapidxml对于C++来说是一个很好的解决方案)

问:需要数据库吗?

是的,我有一些信息/计算需要保存(本地/全局)。-> 本地:我会使用sqlite-> 如果您只需要保存相对较少的信息,请考虑一种更快的存储这些信息的方法(xml?!)

问:应该如何构建我的应用程序?

A:一定要把GUI与“逻辑”部分分开-> 这样更容易在以后更改代码,并且您还可以将代码用于其他项目。 +已经提到的原因。

问:我该如何构建我的GUI?

A:考虑一下您的应用程序应该用于什么以及用户应该能够做什么。还有,请不要创建太深的层次结构,这意味着用户不应该打开10个窗口才能打开他们想要的窗口。对于您的代码也是一样,拥有太多创建新对象的对象不是一个明智的决定。

object->object->object->object->object->object->object->object

问:我的应用程序是否必须与服务器应用程序通信?

答:是的?您将需要使用套接字!但请记住,通过套接字进行通信并不是非常快速和安全的,因此如果没有必要,请勿使用。

问:我不确定如何开始(我们是一组开发人员)

在启动新项目时,我会考虑所有这些点(可能还有更多)+为了看到我需要哪些类和方法,我首先创建一个UML图表,它将帮助我理解我应该从哪里开始,该图表还将帮助我跟踪我的类和方法以及它们如何相互关联。 UML图表还将帮助您的同事或客户了解您的应用程序的结构。

对于更大的项目,我会使用C++和wxWidgets或Qt。(仅代表个人观点)

此致
Layne


1

在编程方面,建议使用Python作为基础GUI语言,并使用QT作为GUI平台。如果将GUI和基础程序分开成不同的进程,则可以使用以下机制进行通信:

  1. 来自Qt的信号和插槽
  2. Python中的子进程模块
  3. 本地套接字。
  4. 使用文件[将配置写入文件并向其他进程发出刷新信号]

但是,最好创建一个进程并直接从Python调用您的基础语言,并与本地语言的数据结构进行通信。您可以使用SWIG实现此目的。但是,由于无法从C ++内部调用Python函数,因此您可以在Python中进行轮询以对共享数据进行一些更改,并根据这些更改执行某些操作。我有两种经验。当我使用Python进行GUI和管理时,它可以节省很多时间。


你说使用Python+QT更好。比什么更好? - Bryan Oakley

1

1. 应该将GUI与应用程序的逻辑分开吗?

是的。然而,请参见答案#2。

2. 如果分离,逻辑和GUI如何通信?TCP/IP套接字是好选择吗?还有其他可能性吗?

我认为最好通过选择一个GUI框架来回答这个问题,例如MFC、.NET、wxWidgets、Qt等等。您选择的框架将为您处理分离和通信,尽可能地减少麻烦。

不要试图重新发明轮子。框架设计者对他们的实现考虑和测试远比您能够负担得起的多。

请注意,问题#1暗示您在询问如何将单个应用程序中的逻辑分离。但是,后面的问题表明您可能正在考虑两个单独的应用程序,甚至在单独的机器上运行。

我认为,在完全单独的应用程序中使用GUI将始终导致某些缓慢和不灵活的结果。但是,如果您不关心速度和灵活性,特别是如果已经使用简单的控制台类型界面运行核心应用程序,那么这可能是最好的方法。

3. GUI使用与C++不同的语言是个好主意吗?如果是,应该选择哪种语言?

不是一个好主意。

如果你是单人编程团队,那么尝试掌握两种语言会让你分身乏术。如果你是多人团队,为什么要设置两种不同的文化来加剧沟通问题呢?

4. 使用基于浏览器的GUI是个好主意吗?

如果可以避免就不要使用。如果你需要基于浏览器的GUI,那么你会知道它的必要性。如果不需要,那么保持简单并跳过它。

5. 即使项目的核心逻辑是跨平台的,我可以决定GUI只基于Windows (.NET?),并通过Socket或类似方法与相关Win/Linux机器上的逻辑进行通信。这样做是个好主意吗?

和问题#4的答案相同。


1

如果您想要一个良好的跨平台 GUI 解决方案的例子,而且还是免费且编写得很好的,我建议您看看 wxWidgets (1)。希望这可以帮到您。


wxWidgets域名现在正在出售。 - Erik Friesen

1

我的回答非常泛泛,因为你没有提供关于你的应用程序的任何信息。

GUI应该与应用程序的逻辑分离吗?

在代码中,当然要分离。在单独的进程中运行,可能在单独的机器上运行,这也取决于您的要求。

完全分离的原因:

  • 在GUI不运行时将应用程序作为守护程序或系统服务(在后台)运行
  • 通过网络远程控制应用程序
  • 可能使用不同的编程语言(例如iPhone)实现多个独立的GUI实现
  • 支持无GUI的自动控制(脚本编写)
  • 如果最初未进行分离,则几乎不可能在以后实现分离

不分离的原因:

  • 需要序列化所有I/O,使实现更加困难
  • 如果传输大量数据,则会略微降低性能(这确实不会以任何方式影响您典型的GUI应用程序)

如果分开,逻辑和GUI应该如何通信? TCP / IP套接字是一个好选择吗?还有其他可能性吗?

HTTP是一种流行的选择,它避免了大多数防火墙等问题。在C/C++中,您可以使用libcurl进行http/https请求,使用Boost.CGI(尚未被Boost接受)或其他CGI库进行服务器端。

IPC的其他选项包括共享内存(Boost.Interprocess)、UNIX套接字和其他网络协议。但是,除非传输大量数据,否则我不建议使用这些选项。

将GUI放在与C++不同的语言中是否是一个好主意?如果是,应该用哪种语言?

我认为没有太多好处。不过,将GUI分离出来可以使用不同的语言编写它,甚至可以编写多个实现。

将GUI放在基于浏览器的界面上是否是一个好主意?

绝对是。如果您所需的功能可以使用HTML5和JavaScript完成,那么根本不要考虑传统的GUI,而是将其制作成Web应用程序。

好处有:

  • 完全跨平台
  • 无需在用户机器上安装软件
  • 所有客户端始终使用最新版本的GUI
  • Web GUI框架实际上比传统的GUI框架更好用
  • 无需将GUI分离成单独的进程
  • 仍然可以从脚本中使用(例如使用shell脚本中的curl程序)

另一方面,您将会有轻微的性能下降,但再次强调,这对于典型的GUI应用程序没有足够影响。

尽管项目的核心逻辑是跨平台的,我可以决定GUI只基于Windows (.NET?),并通过Socket或类似方法与相关的Win/Linux机器通信。这样做是个好主意吗?

跨平台GUI库的API有些可怕。Qt现在在本地外观方面做得非常好,并且其API相当不错,尽管它会对您的应用程序产生重大影响。尽量将Qt的使用限制在GUI上。真正本地的跨平台GUI的另一个选项是wxWidgets,它与其他C++代码集成得更好,但其API非常恶心和容易出错。

对于 Web UI,你应该考虑使用 Wt。它是一个高级的 C++ AJAX 框架,界面类似于 Qt,但使用现代 C++ 实践而不是像 Qt 那样接管你的应用程序。


1

我同意那些说“信息不足”的评论者,但根据您的需求,您应该非常考虑使用Web浏览器界面。

如果实时流数据和即时满足的交互性不重要,则Web界面可以相当简单,没有AJAX,只有微不足道的基于表单的CGI和动态生成的HTML。请记住,作为浏览器的部分正在使用其他人的资金进行更新,以及Windows、Linux、Mac或其他系统的任何更改。

您的用户已经熟悉了这一点。您可以找到程序员来完成工作。如果需要,几乎每种主要语言都存在将Web服务器嵌入应用程序中的库。或者您可以运行某种集中式服务器。

浏览器已经具有很好的内容、输入(表单)、样式和增强功能分离的方法,未来很容易找到能够开发或更换相关组件的人。

有些人可能会说这对于应用程序的独立版本不好,但我认为只要添加一些安全性(运行嵌入式Web服务器,仅当请求来自本地计算机时才回答),那么这对于独立版本来说就没问题了。可以通过从应用程序启动浏览器或在启动消息中告诉用户去哪里(URL http://localhost:7654 或其他位置,而不是他们永恒的目的地 :-)) 来使用户的生活更轻松。

0
  1. 应该将GUI与应用程序逻辑分离吗?

是的。

  1. 如果要分开,逻辑和GUI应如何通信?TCP/IP套接字是一个好选择吗?还有哪些可能性?

TCP/IP太过冗长。使用OOP或任何其他结构化编程方法将应用程序逻辑和GUI分开。

  1. 将GUI放在不同于C ++的语言中是否是个好主意?如果是,用哪种语言?

就跨平台应用而言,C ++已足够好。其他选项是Java和.NET,在这种情况下,大部分跨平台内容都得到了解决......尽管没有C ++提供的控制程度高。

  1. 将基于浏览器的GUI是一个好主意吗?

只要您的应用程序在用户交互期间不需要太细致的控制,这是最好的想法。

  1. 尽管项目的核心逻辑是跨平台的,但我可以决定GUI仅基于Windows(.NET?),并通过Socket或类似方法与相关Win / Linux机器上的逻辑通信。这样做是个好主意吗?

在我看来,使用套接字增加的复杂性不值得。

SciTE是一个相当不错的简单跨平台应用程序示例。源代码应该很容易让Windows程序员理解。我建议您下载源代码并查看如何处理同一代码库的两个平台(Windows和GTK)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接