Die grausame MDI

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo Leute,

ich lerne gerade Qt4 kennen. Ich habe per Qt-Designer ein MainWindow erstellt, mit dazugehörigem Menu. Nun arbeite ich an einem SysTray, also, die MDI in Systray zu verlegen. Vor diesem Hintergrund habe ich gleich zwei Fragen. Erst einmal den Code:

Code: Alles auswählen

import sys
import os

from PyQt4.QtCore import *
from PyQt4.QtGui import QApplication, QMainWindow, QWorkspace, QAction, QMenu, QSystemTrayIcon, QIcon, QMessageBox
from PyQt4.uic import *

class Mdi_Main(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.path_mdi_form =  os.path.abspath(".")

        self.trayIconMenu = QMenu()

        self.createActions()

        self.ui_TestMainWorkSpace = loadUi(self.path_mdi_form + '\\files\qt_ui\mdi_form.ui', self)
        self.ui_TestMainWorkSpace.showMaximized()

        self.workspace = QWorkspace()
        self.workspace.setScrollBarsEnabled(True)
        self.setCentralWidget(self.workspace)

        self.ui_TestMainWorkSpace.setWindowTitle("MDIForm")


        self.set_SysTray = self.actionSysTray.setText("Start in SysTrayIcon")

        # Signal / Slot
        self.ui_TestMainWorkSpace.actionSysTray.triggered.connect(self.createTrayIcon)


    def createActions(self):
        self.aboutAction = QAction("About", self,
                triggered=self.showAbout)
        self.maximizeAction = QAction("Show Appliacation", self,
                triggered=self.showMaximized)
        self.quitAction = QAction("Quit Application", self,
                triggered=app.quit)

    def createTrayIcon(self):
        print "Los"
        self.w = self.ui_TestMainWorkSpace
        self.trayIconMenu.addAction(self.aboutAction)
        self.trayIconMenu.addAction(self.maximizeAction)
        self.trayIconMenu.addSeparator()
        self.trayIconMenu.addAction(self.quitAction)

        self.trayIcon = QSystemTrayIcon(QIcon('about.png'), self.w)
        self.trayIcon.setContextMenu(self.trayIconMenu)
        self.trayIcon.show()

        self.hide()

    def showAbout(self):
        self.ui_about = loadUi(self.path_mdi_form + '\\files\qt_ui\pp_about.ui')
        self.ui_about.show()



app = QApplication(sys.argv)
window = Mdi_Main()
sys.exit(app.exec_())

Ich weiß, man solle QWorkspace nicht mehr benutzen, aber für meinen Test sollte es auch nicht von Bedeutung sein.

Folgendes Problem: Sobald meine MDIForm nun im SysTray ist, und ich über das SysTray-Menu auf "About" (Zeile 44) gehe, ich über die showAbout(self)-Funktion (Zeille 55) die pp_about.ui (Zeile 58) dynamisch laden und anschließend anzeigen lassen (Zeile 59). Die Form wird angezeigt. Aber beim schließen der Form wird gleich die gesamte MDIForm geschlossen. Wie kann ich das verhindern? Schließlich will man ja nicht nach einem "Über Prgramm" gleich das gesamte Programm beenden :-)

Zweites Problem: Wie ihr in Zeile 50 seht, versuche ich ein Icon zu laden, damit dieser im SysTray zusehen ist. Jedoch ist dort nichts zu sehen, nur ein leerer Platzhalter. Aber der Menu ist trotzdem da. Das Icon liegt im selben Ordner wie die ausgeführte Datei.

Besten Dank
Euer Sophus
Benutzeravatar
Madmartigan
User
Beiträge: 200
Registriert: Donnerstag 18. Juli 2013, 07:59
Wohnort: Berlin

Du solltest schon lauffähigen Code bereitstellen, hier fehlen z.B. die *.ui Dateien. actionSysTray ist daher für uns unbekannt. Ein Test des Codes ist so eben nicht möglich.

Ein paar Hinweise:
Verwende keine Sternchen-Importe, das ist ganz schlechter Stil.
Du hast es ja selbst gesagt, und die offizielle Doku sagt es auch ("[...] strongly recommend to NOT use it"). QWorkspace ist veraltet und sollte nicht verwendet werden. Auch nicht für Testzwecke.
Variablennamen sollten verständlich und aussagekräftig sein. self.w ist keine gute Wahl.
Wenn du den Designer zur Erstellung der GUI verwendest, warum setzt du WindowTitle explizit im Code?
Schau dir bitte den StyleGuide an (PEP8), Methodennamen sollten nicht in CamelCase/PascalCase geschrieben werden, sondern durch Unterstriche getrennt werden. Statt createActions() quasi create_actions().
BlackJack

@Sophus: Ergänzend zum `self.w`, das ist ja eine Abkürzung für `self.ui_TestMainWorkSpace`, was gar kein Workspace ist sondern ein `QMainWindow`, und da Du wieder `self` als zweites Argument beim laden der ``*.ui`` angegeben hast ist beides das selbe wie `self`. Es gibt also *drei* mögliche Wege an das gleiche heran zu kommen. Wobei `self.w` erst nach `createTrayIcon()` vorhanden ist und anscheinend auch nirgendwoanders benutzt wird. Das sollte also kein Attribut des Widgets sein.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hier, ein lauffähiges Programm.

Wie gesagt, sobald das Programm im Systray ist, und ich im SysTray-Menu auf "Info" klicke, wird das andere Fenster angezeigt. Schließe ich das eben geöffnet Fenster, schließt sich das gesamte Programm. Ich habe eure Hinweise beachtet, aber in diesem Code erstmal nicht umgesetzt. Es ist immer noch der alte Code, ohne PEP8 etc.

mdi_form.ui

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget"/>
  <widget class="QStatusBar" name="statusbar"/>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>21</height>
    </rect>
   </property>
   <widget class="QMenu" name="menuManagement">
    <property name="title">
     <string>menuManagement</string>
    </property>
    <addaction name="separator"/>
    <addaction name="actionSysTray"/>
   </widget>
   <addaction name="menuManagement"/>
  </widget>
  <action name="actionAddContact">
   <property name="text">
    <string>addContact</string>
   </property>
  </action>
  <action name="actionAddMovie">
   <property name="text">
    <string>actionAddMovie</string>
   </property>
  </action>
  <action name="actionAddSerie">
   <property name="text">
    <string>actionAddSerie</string>
   </property>
  </action>
  <action name="actionAddAlbum">
   <property name="text">
    <string>actionAddAlbum</string>
   </property>
  </action>
  <action name="actionAddSingle">
   <property name="text">
    <string>actionAddSingle</string>
   </property>
  </action>
  <action name="actionAddRecord">
   <property name="text">
    <string>actionAddRecord</string>
   </property>
  </action>
  <action name="actionSysTray">
   <property name="text">
    <string>SysTray</string>
   </property>
  </action>
  <action name="actionClose">
   <property name="text">
    <string>actionClose</string>
   </property>
  </action>
  <action name="actionComic">
   <property name="text">
    <string>actionComic</string>
   </property>
  </action>
  <action name="actionBook_2">
   <property name="text">
    <string>actionBook_2</string>
   </property>
  </action>
 </widget>
 <resources/>
 <connections/>
</ui>
pp_about.ui

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>494</width>
    <height>541</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Fenster</string>
  </property>
  <layout class="QGridLayout" name="gridLayout_2">
   <item row="0" column="0">
    <widget class="QTabWidget" name="tabWidget">
     <property name="currentIndex">
      <number>0</number>
     </property>
     <widget class="QWidget" name="Tab1">
      <attribute name="title">
       <string>Tab 1</string>
      </attribute>
     </widget>
     <widget class="QWidget" name="Tab2">
      <attribute name="title">
       <string>Seite</string>
      </attribute>
     </widget>
     <widget class="QWidget" name="Tab3">
      <attribute name="title">
       <string>Tab 2</string>
      </attribute>
      <widget class="QLabel" name="label">
       <property name="geometry">
        <rect>
         <x>10</x>
         <y>10</y>
         <width>361</width>
         <height>41</height>
        </rect>
       </property>
       <property name="text">
        <string>TextLabel</string>
       </property>
      </widget>
     </widget>
     <widget class="QWidget" name="Tab4">
      <attribute name="title">
       <string>Seite</string>
      </attribute>
     </widget>
    </widget>
   </item>
   <item row="1" column="0">
    <layout class="QVBoxLayout" name="verticalLayout">
     <item>
      <widget class="QPushButton" name="pushButtonClose">
       <property name="text">
        <string>PushButton</string>
       </property>
      </widget>
     </item>
    </layout>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>
UI_mdi_form.py

Code: Alles auswählen

import sys
import os

from PyQt4.QtCore import *
from PyQt4.QtGui import QApplication, QMainWindow, QWorkspace, QAction, QMenu, QSystemTrayIcon, QIcon
from PyQt4.uic import *
# Forms
from UI_pp_about import About_Window


class Mdi_Main(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.createActions()
        self.ui_TestMainWorkSpace = loadUi('mdi_form.ui', self)
        self.ui_TestMainWorkSpace.showMaximized()


        self.workspace = QWorkspace()
        self.workspace.setScrollBarsEnabled(True)
        self.setCentralWidget(self.workspace)

        self.ui_TestMainWorkSpace.setWindowTitle("MDI Formular")

        self.management = self.ui_TestMainWorkSpace.menuManagement.setTitle("Menuleiste_1")

        self.set_SysTray = self.ui_TestMainWorkSpace.actionSysTray.setText("Im TrayIcon")

        # Signal / Slot
        self.ui_TestMainWorkSpace.actionSysTray.triggered.connect(self.createTrayIcon)

    def createActions(self):
        self.aboutAction = QAction("Info...", self,
                triggered=self.create_About)
        self.maximizeAction = QAction("Anzeigen", self,
                triggered=self.showMaximized)
        self.quitAction = QAction("Beenden", self,
                triggered=app.quit)

    def createTrayIcon(self):
        self.hide()
        self.trayIconMenu = QMenu(parent=self)
        self.trayIconMenu.addAction(self.aboutAction)
        self.trayIconMenu.addAction(self.maximizeAction)
        self.trayIconMenu.addSeparator()
        self.trayIconMenu.addAction(self.quitAction)

        self.trayIcon = QSystemTrayIcon(QIcon('world.png'), self)
        self.trayIcon.setContextMenu(self.trayIconMenu)
        self.trayIcon.show()

    def create_About(self):
        self.ui_pp_about = About_Window()
        self.ui_pp_about.show()

app = QApplication(sys.argv)
window = Mdi_Main()
sys.exit(app.exec_())
UI_pp_about.py

Code: Alles auswählen

import sys
import os

from PyQt4.QtCore import *
from PyQt4.QtGui import QDialog
from PyQt4.uic import *

class About_Window(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)

        self.ui_pp_about = loadUi('pp_about.ui', self)
        self.ui_pp_about.setWindowModality(Qt.ApplicationModal)
        self.ui_pp_about.show()

        self.ui_pp_about.setWindowTitle("Ein neues Fenster")
        self.ui_pp_about.pushButtonClose.setText("Beenden")
        self.ui_pp_about.tabWidget.setTabText(0, "Tab1") # First Tab
        self.ui_pp_about.tabWidget.setTabText(1, "Tab2") # Second Tab
        self.ui_pp_about.tabWidget.setTabText(2, "Tab3") # Third Tab
        self.ui_pp_about.tabWidget.setTabText(3, "Tab4") # Fourth Tab
        self.ui_pp_about.pushButtonClose.clicked.connect(self.close)

Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@Sophus: Bitte nutze für so langen Quellcode besser ein Pastebin, wie das eingebaute hier im Forum - oder bei mehreren Dateien vermutlich praktischer gist.github.com.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Sophus: Schau Dir mal `quitOnLastWindowClosed()` auf `QApplication` an. Dein Programm endet nämlich nur wenn Du ein Fenster schliesst und das das letzte angezeigte war. Wenn Du zum Beispiel das Hauptfenster wieder sichtbar machst und *dann* den Info-Dialog aufrufst und schliesst, beendet sich das Programm nicht.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@Hyperion: Wo finde ich diese besagte Pastebin?

Hallo BlackJack, ich habe im Modul UI_pp_about.py eine Funktion eingebaut (Zeile 25-27). Würdest du das auch so lösen? Also, soweit funktioniert das auch alles ganz super. Ein kleines Problem folgt jedoch. Anscheint wird das QMenu danach zerstört. Das Programm schließt sich nicht, das Icon ist im SysTray zu sehen, aber ich kriege kein Menu mehr auf, um vielleicht das Programm zu beenden oder nochmal das "About"-Fenster anzeigen zu lassen.

Edit: Ein weiteres Problem hat sich eingeschlichen. Wenn ich das UI_pp_about.Modul direkt öffne, also nicht über SysTray-Menue, sondern über MDI, und dann wieder schließe, ist die Menuleiste dort deaktiviert bzw. nicht mehr anklickbar. Irgendwas mache ich hier gewaltig falsch.

Code: Alles auswählen

import sys
import os

from PyQt4.QtCore import *
from PyQt4.QtGui import QDialog, QApplication
from PyQt4.uic import *

class About_Window(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)

        self.app = QApplication(sys.argv)
        self.ui_pp_about = loadUi('pp_about.ui', self)
        self.ui_pp_about.setWindowModality(Qt.ApplicationModal)
        self.ui_pp_about.show()

        self.ui_pp_about.setWindowTitle("Ein neues Fenster")
        self.ui_pp_about.pushButtonClose.setText("Beenden")
        self.ui_pp_about.tabWidget.setTabText(0, "Tab1") # First Tab
        self.ui_pp_about.tabWidget.setTabText(1, "Tab2") # Second Tab
        self.ui_pp_about.tabWidget.setTabText(2, "Tab3") # Third Tab
        self.ui_pp_about.tabWidget.setTabText(3, "Tab4") # Fourth Tab
        self.ui_pp_about.pushButtonClose.clicked.connect(self.set_close)

    def set_close(self):
        self.app.quitOnLastWindowClosed()
        self.close()
BlackJack

@Sophus: `QApplication` ist das Objet das für *die* Anwendung steht. Davon darf man AFAIK nicht mehr als eins erstellen. Und `quitOnLastWindowClosed()` ist auch die falsche Methode um den Wert zu *setzen*. Die Zeile hat in dem Programm keinen Effekt.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@BlackJack: Ich müsste dieses quitOnLastWindowClosed also in MainWindow platzieren, denn im UI_pp_about-Modul gibt es ja keine QApplication. So würde ich zumindest denken.
BlackJack

@Sophus: Hast Du denn überhaupt in der Dokumentation nachgelesen was es mit diesem ”Property” auf sich hat?
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Wie ich schon dachte, nahm ich mir die MainWindow vor:

Code: Alles auswählen

import sys
import os

from PyQt4.QtCore import *
from PyQt4.QtGui import QApplication, QMainWindow, QWorkspace, QAction, QMenu, QSystemTrayIcon, QIcon
from PyQt4.uic import *


# Forms
from UI_pp_about import About_Window


class Mdi_Main(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.createActions()
        self.ui_TestMainWorkSpace = loadUi('mdi_form.ui', self)
        self.ui_TestMainWorkSpace.showMaximized()


        self.workspace = QWorkspace()
        self.workspace.setScrollBarsEnabled(True)
        self.setCentralWidget(self.workspace)

        self.ui_TestMainWorkSpace.setWindowTitle("MDI Formular")

        # Set languages for  menuebar
        self.management = self.ui_TestMainWorkSpace.menuManagement.setTitle("Menuleiste_1")


        self.set_SysTray = self.ui_TestMainWorkSpace.actionSysTray.setText("Im TrayIcon")


        # Signal / Slot
        self.ui_TestMainWorkSpace.actionSysTray.triggered.connect(self.createTrayIcon)

    def createActions(self):
        self.aboutAction = QAction("Info...", self,
                triggered=self.create_About)
        self.maximizeAction = QAction("Anzeigen", self,
                triggered=self.showMaximized)
        self.quitAction = QAction("Beenden", self,
                triggered=app.quit)

    def createTrayIcon(self):
        self.hide()
        self.trayIconMenu = QMenu(parent=self)
        self.trayIconMenu.addAction(self.aboutAction)
        self.trayIconMenu.addAction(self.maximizeAction)
        self.trayIconMenu.addSeparator()
        self.trayIconMenu.addAction(self.quitAction)

        self.trayIcon = QSystemTrayIcon(QIcon('world.png'), self)
        self.trayIcon.setContextMenu(self.trayIconMenu)
        self.trayIcon.show()

    def create_About(self):
        self.ui_pp_about = About_Window()
        self.ui_pp_about.show()

app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(False) # 
window = Mdi_Main()
sys.exit(app.exec_())
Es scheint zu funktionieren. Was mich hierbei sehr verwundert, ist, dass ich es auf "False" stellen musste. Ich bin davon ausgegangen, dass ich es auf True setzen muss. Lesen würde ich das dann wie folgt: Setze setQuitOnLastWindowClosed auf True, damit das gesamte Programm nicht beendet wird, solange das letzte Fenster noch offen ist.

Denn in der Dokumentation steht:
This property holds whether the application implicitly quits when the last window is closed.
The default is true.
If this property is true, the applications quits when the last visible primary window (i.e. window with no parent) with the Qt::WA_QuitOnClose attribute set is closed.
Oder ist mein englisch mächtig eingerostet? :-)
BlackJack

@Sophus: Dann ist dein englisch eingerostet, denn die Dokumentation sagt genau das Gegenteil von Deiner ursprünglichen Vermutung. Wobei das IMHO auch der Name des Flags selber auch schon das richtige aussagt. Zu deutsch `verlasseProgrammWennLetztesFensterGeschlossen`. Das verlässt das Programm wenn das letzte Fenster geschlossen wird. Und genau das möchtest Du ja nicht. Und `True` ist ja auch der Defaultwert. Wenn man also das Verhalten verändern möchte macht es ja keinen Sinn den Defaultwert noch mal zu setzen.

Übrigens musst Du Dich jetzt natürlich explizit darum kümmern dass das Programm beendet werden kann weil es eben nicht mehr automatisch endet wenn keine Fenster mehr angezeigt werden.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@BlackJack: Oder meine Logik versagt gerade. Denn ich möchte sehr wohl, dass meine MainWindow nicht geschlossen wird, sobald ein QWidget oder ein QDialoge geschlossen wird. Aber egal, ich denke einfach zu viel :-)

Zu deiner Anmerkung, ich würde mir wie folgt darum kümmern:

Code: Alles auswählen

        self.ui_TestMainWorkSpace.actionClose.triggered.connect(app.quit)
Mit der quit()-Methode würde ich das also lösen.
BlackJack

@Sophus: Den Satz mit dem MainWindow verstehe ich jetzt nicht‽ Das Flag bestimmt ob das Programm beendet wird wenn kein Fenster mehr angezeigt wird. Wenn Du einen Dialog schliesst und das Hauptfenster noch offen ist dann wird ja auch nach dem schliessen des Dialogs das Hauptfenster angezeigt und damit natürlich *nicht* das Programm beendet. Nur wenn gar kein Fenster mehr angezeigt wird, also auch das Hauptfenster nicht mehr, dann endet das Programm. Das ist ja auch genau das was man als Normalfall haben möchte. Wenn man alle Fenster schliesst, endet das Programm. Du hast jetzt einen Sonderfall kreiert in dem Du zwar kein Fenster mehr hast, aber wegen dem Trayicon trotzdem möchtest dass das Programm weiterläuft. Da muss man dann sagen das man sich selbst darum kümmert wann das Programm tatsächlich beendet ist.

Ist das eigentlich nur Spielerei oder soll das tatsächlich eine Anwendung mit einem Trayicon werden die man nicht so leicht über den üblichen Weg schliessen kann? Mit so etwas würde ich vorsichtig umgehen. Wie überhaupt mit Trayicons. Die sollte man eigentlich nur verwenden wenn man Programme hat die im Hintergrund irgendetwas machen und dem Benutzer zur jeder Zeit etwas signalisieren können sollen. Also Kommunikationsprogramme (E-Mail, Chat, Downloader, …) oder Dienste die irgendwelche Zustände anzeigen die der Anwender ständig im Blick haben sollte (Virenscaller, Hardwaremonitoring, Netzwerksoftware, …). Und das mit dem nicht schliessen obwohl kein Fenster mehr da ist, sollte ein Programm sein was *in dem Zustand* etwas *macht* und dann nicht einfach nur nutzlos darauf wartet das der Benutzer es wieder als Fenster darstellen lässt. Denn *das* bietet das System ja schon über das Minimieren von Fenstern.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@BlackJack: Sowohl als auch. Zunächst ist es eine Spielerei, denn ich will mich mit dem QT-Designer und das Arbeiten mit den *.ui-Dateien im Python vertraut machen. Jedoch lernt man ja nicht einfach nutzlose Sachen, sondern auch Sachen, die man anwenden möchte. Trifft nicht immer zu, aber oftmals. Deine Anmerkung finde ich völlig berechtigt. Aber ich habe hier auch Programme laufen, die im TrayIcon liegen. Zum Beispiel mein VLC-Player, meinen PDF-Creator und einiges mehr. Es ist eher praktisch. Das mit dem Minimieren müllt die Taskleiste unendlich zu. Denn in der Tasklaste liegen Programme die sowohl minimiert als auch angezeigt werden. Dann lieber verlege ich das Programm gern in den TrayIcon - wirkt aufgeräumter. Außerdem werde ich nicht so penetrant mit dem TrayIcon arbeiten. Das heißt, meine Intention zielt darauf hinaus, dass der Anwender es sich aussuchen kann, ob das Programm in ein TrayIcon verlegt werden soll oder nicht. Die Entscheidung liegt also beim Anwender.
BlackJack

@Sophus: Die beiden genannten Programme fallen ja in die Kategorien von Programmen die im Hintergrund laufen. VLC als Videoplayer genutzt natürlich nicht, weil man dann das Fenster ja natürlich sehen will, oft sogar im Vollbildmodus. Aber wenn man ihn als Audioplayer oder Streamingserver verwendet, dann möchte man jederzeit schnellen Zugriff haben. Und PDFCreator ist ja auch ein Dienst der im Hintergrund läuft und weniger ein ”normales” Programm.
Antworten