# Toolkit für prinzipiell ganz einfaches Programm

## l3u

Hallo allerseits :-)

Ich will ein augenscheinlich einfaches Problem lösen, weiß nur mangels vorhandener Erfahrung in GUI-Programmierung nicht wie und wäre für jede Hilfe dankbar! Folgendes will ich machen:

Ich brauche ein Fenster, was entweder transparent ist oder gerne auch pseudo-transparent, heißt, einfach einen Screenshot des Bereichs macht, der hinter dem Fenster wäre, wenn es nicht da wäre. Und dann will ich mittels einer Linie, die durch mehrere Punkte definiert ist, einen Bereich markieren können.

Das war’s schon. Problem ist nur, dass das Ganze auch unter Windows XP laufen muss. Verwenden würde ich gerne Python (am liebsten Python 3) dafür, weil ich das einigermaßen kann. Nur was für ein Toolkit nimmt man? Qt? GTK?

Sinn des Programms soll sein, dass ich erst mit einer Linie ein Objekt bekannter Länge markiere, dann ausrechne, wie viele Pixel lang die Linie ist, und somit per Dreisatz dann ein anderes Objekt unbekannter Länge mittels einer weiteren Linie vermessen kann.

Kann mir jemand einen Tip geben, wo ich damit anfangen könnte? Vielen Dank schonmal!

----------

## Finswimmer

Evtl kannst du das auch ohne GUI machen?

Du könntest in einer cmd/shell anzeigen lassen:

Punkt 1 anklicken

Punkt 2 anklicken 

usw.

Mit Enter beenden

Bei jedem Mausklick lässt du dir die Koordinate der Mausposition ausgeben und berechnest damit die Distanz.

Das Ganze sieht dann evtl. unschön aus, aber ist dafür ohne großen Aufwand machbar.

http://www.daniweb.com/software-development/python/code/230886/get-the-mouse-position-on-the-screen-on-linux#

http://stackoverflow.com/questions/3698635/geting-cursor-position-in-python

----------

## l3u

Die Striche müsste ich schon sehen können, um sicher zu sein, dass ich auch richtig kalibriert/gemessen habe …

----------

## firefly

Mit pseudo transparenz würdest du nicht weit kommen. Denn AFAIK kann ein Programm nur den "Desktop" Hintergrund bekommen welches sich unterm dem Breich befindet wo sich das Fenster befindet. (Wobei das nur für den X-Server gilt)

Und für echte Transparents benötigst du unter linux mit einem X-Server einen laufenden composite manager.

Du könntest aber einfach mit einem (externen) Programm einen Screenshot von der entsprechende Stelle machen.

Und dann das Bild in deinem Programm laden und anzeigen.

----------

## l3u

Einen Screenshot zu machen ist kein Problem. Das hab ich schon mit Qt und GTK gemacht, man müsste ja bloß die Koordinaten des Fensters wissen, dann das Fenster Ausblenden, einen Desktop-Screenshot mit dem passenden Ausschnitt machen und gut.

Echt Transparenz wäre hier denke ich übertrieben, weil ich die eigentlich nicht brauche, sondern nur ein statisches Bild. Und das wird denke ich auch ein Problem unter Windows XP sein, oder?

----------

## l3u

Update: ich hab’s mit Python 3.3 und PyQt4 gemacht. War deutlich einfacher als gedacht – und läuft 1:1 genauso unter Windows. Einwandfrei :-)

----------

## cryptosteve

Zeigen!  :Smile: 

----------

## l3u

Nicht hauen, ist mein allererstes Programm mit GUI ;-)

Ist unter svn://l3u.de/nasauber.de/trunk/endomess zu finden.

endomess.ui muss noch mittels pyuic4-3.2 in Python-Code übersetzt werden, und zwar nach endomess_ui.py.

Kurz und knapp also:

```
svn export svn://l3u.de/nasauber.de/trunk/endomess && cd endomess && pyuic4-3.2 endomess.ui > endomess_ui.py
```

„Load“ macht einen Screenshot, danach wird automatisch der Knopf „Calibrate“ geklickt. Eine Linie markiert man mit Linksklicks, Beendet wird die Linienerstellung mit einem Rechtsklick. Nach dem Kalibrieren das mm-Maß des markierten Objekts eingeben und „OK“ klicken. Dann wird automatisch der „Measure“-Knopf geklickt. Danach kann man was messen, die Linie wird wie beim Kalibrieren erstellt.

Was sicher nicht ganz „sauber“ ist: das sleep(0.3) in getScreenshot() – aber ansonsten war das Fenster selber auf dem Screenshot. Und habe auf Anhieb auch keine Möglichkeit gefunden, wie ich herausfinden kann, wann das Fenster wirklich ausgeblendet ist.

----------

## franzf

sleep unterbricht einfach die Ausführung. Dass es funktioniert kann ich mir nur dadurch erklären, dass im Hintergrund X asynchron noch arbeitet.

Sauber wäre es, das Pixmap holen + anschließendem show() in einen separaten SLOT zu legen und diesen direkt nach dem hide() per QTimer.singleshot() aufzurufen. Damit der User sieht, dass gerade gearbeitet wird, kannst du noch Qt.WaitCursor als overrideCursor setzen (->QApplication) und vor dem show() natürlich restoreOverrideCursor nicht vergessen  :Smile: 

----------

## l3u

Sorry, ist nicht nur mein erstes Programm mit GUI, sondern auch mein erstes Qt-Programm …

Das sind doch bestimmt nur ein paar Zeilen Code, oder? Würdest du mir verraten, welche? ;-)

Ich hab nicht rausfinden können, wie ich herausbekomme, wann das Fenster tatsächlich weg ist. Das hide() allein ist jedenfalls viel zu schnell, wie gesagt: ohne sleep() ist das Fenster selbst auf dem Screenshot drauf.

----------

## franzf

Ich meinte auch gar nicht, dass du das herausfinden sollst. Nur das sleep durch QTimer ersetzen:

```
--- endomess.py.org     2012-11-19 14:08:56.283706491 +0100

+++ endomess.py 2012-11-19 14:11:13.701697217 +0100

@@ -33,8 +33,9 @@

                self.delItems(self.screenshot.pixmapType)

 

                self.hide()

-               sleep(0.3)

-

+               QTimer.singleShot(300, self.doGetAndShow)

+

+       def doGetAndShow(self):

                screenshotPic = QGraphicsPixmapItem(QPixmap.grabWindow(

                        QApplication.desktop().winId(),

                        x = self.geometry().x(),
```

Wenn du dann nach dem hide() ein

```
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
```

Und vor dem show in doGetAndSow

```
QApplication.restoreOverrideCursor()
```

Ob die 300ms ausreichen hängt übrigens vom System des Benutzers und deren Auslastung ab (normalerweise sollte es aber locker reichen).

Ich muss jetzt aber noch hinterherschieben, dass ich das gerade nicht testen kann, da der Rechner an dem ich gerade sitze kein PyQt4 installiert hat... Wenn es NICHT klappt einfach nochmal melden  :Smile: 

machst, weiß der User auch was los ist.

----------

## l3u

Es geht so, aber interessanterweise erscheint das Fenster hinterher nicht an der selben Stelle, sondern immer im rechten oberen Eck des Bildschirms. Der Screenshot passt aber … vorher ist es zumindest ungefähr wieder da erschienen, wo es vorher war, nur ein Bisschen (um die Höhe der Fensterleiste?) nach unten versetzt.

Interessant wäre an dieser Stelle sicher, den Screenshot pixelgenau machen zu können und das Fenster auch exakt da wieder erscheinen zu lassen, wo es vorher war. Mir ist ohnehin nicht ganz klar, warum das Fenster (bei beiden Varianten) nach dem show() woanders auftaucht, als es vorher war.

----------

## AmonAmarth

 *l3u wrote:*   

> Es geht so, aber interessanterweise erscheint das Fenster hinterher nicht an der selben Stelle, sondern immer im rechten oberen Eck des Bildschirms. Der Screenshot passt aber … vorher ist es zumindest ungefähr wieder da erschienen, wo es vorher war, nur ein Bisschen (um die Höhe der Fensterleiste?) nach unten versetzt.
> 
> Interessant wäre an dieser Stelle sicher, den Screenshot pixelgenau machen zu können und das Fenster auch exakt da wieder erscheinen zu lassen, wo es vorher war. Mir ist ohnehin nicht ganz klar, warum das Fenster (bei beiden Varianten) nach dem show() woanders auftaucht, als es vorher war.

 

speicher die fensterposition vor dem hide ab und setze sie nach dem show weider dort hin. wahrscheinlich ordnet der fenstermanager die fenster neu an.

----------

## l3u

Hab ich schon ausprobiert, ändert aber nichts – getestet mit gespeicherten Werten von geometry() und frameGeometry() und einem setGeometry() hinterher.

----------

## py-ro

Wozu Überhaupt der Screenshot, theoretisch müsstest auch einfach direkt auf den Bildschirm malen können, statt eines Fensters ein leeres Widget verwenden und darauf zeichnen. 

Aber ich hab das selber noch nicht ausprobiert.

Bye

Py

----------

## firefly

 *py-ro wrote:*   

> Wozu Überhaupt der Screenshot, theoretisch müsstest auch einfach direkt auf den Bildschirm malen können, statt eines Fensters ein leeres Widget verwenden und darauf zeichnen. 
> 
> Aber ich hab das selber noch nicht ausprobiert.
> 
> Bye
> ...

 

Wie stellst du dir ein "leeres WIdget" vor? Etwa voll Transparenz aber trotzdem mit fenster rahmen?.

Wenn ja, dann geht das unter linux/X11 nur indem eine Mask verwendet wird, welche angibt welche stellen des fensters gezeichnet werden soll oder nicht.

Wie es aber unter windows aussieht weis ich nicht, vermutlich ähnliches.

Ansonsten ist unter linux für "echte" Transparenz nur im zusammenspiel mit einem compositing manager (z.b. compiz) möglich

----------

## l3u

Funktioniert dann allenfalls mit echter Transparenz, weil ein leeres Widget dann trotzdem auf dem opaken Fenster angezeigt wird. Und dann sieht man halt das leere Fenster. Aber generell ist das mit dem Screenshot gut, weil man dann auch das Fenster verschieben kann, ohne dass die Zeichnung nicht mehr zum Bild passt.

Edit: … und außerdem das, was firefly (gleichzeitig mit mir) gepostet hat ;-)

----------

## py-ro

Ich vergaß das xorg ja noch Steinzeit in manchen belangen ist.   :Evil or Very Mad: 

----------

## firefly

 *py-ro wrote:*   

> Ich vergaß das xorg ja noch Steinzeit in manchen belangen ist.  

 

Im vergleich zu Windows ist das aktuelle xorg auf gleicher technischer höhe, was die echte transparenz von fenstern betrifft. Nur halt muss ein composite manager laufen.

In windows ist dieser manager halt schon seit mindestens Windows XP fester bestandteil des "fenster"/Graphik systems.

----------

