[ todo ] PyQt で画像のビューアを作る version 20

2019/06/21 16:21 by yamasyuh68
  :追加された部分   :削除された部分
(差分が大きい場合、文字単位では表示しません)
todo PyQt で画像のビューアを作る
@[TOC](項目)


- まずテキスト表示を試してみる
①単純に現在のlabelにsettextしてみる
②ダメならlabelにlabelを子供としてセットしてみる
addwidget ?
label=QLabel(label)  でいけないかな?

-  ↑ 190620にやってみたけどダメだった┐('д')┌
①は画像が消えて文字だけになってしまいます
②は何も変わりません
QLabelは子供を持つことが出来ないのか??

あくまでwifgetを配置
 labelの子供じゃ無くてmainwindowに直接配置するか?
 レイアウトを解除するか?
QPainterで上書き
 DCを取得して書き込んでしまう


ラベルのペイントイベント
 QWidget.paintEvent (self, QPaintEvent)

 label.paintEvent()

ペインターを動かすにはデバイスが必要
 QPainter.__init__ (self, QPaintDevice)
 QPixmapはデバイスの承継だからこれに直接書ける

--------------
QPainter Class Reference [QtGui module]

dc=QPainter( pixmap )
dc.begin()
dc.drawText( 0,0, 'hogetta' )
dc.end()
- 参考
```
    # ペンの色を指定
23.    painter.setPen(Qt.red)
24.    #painter.setPen(QColor(255, 0, 0))
25.    
26.    # 使用するフォントを指定
27.    painter.setFont(QFont('Times', 30))
28.    # テキスト描画
29.    painter.drawText(image.rect(), Qt.AlignCenter, 'Symfoware')
30.    # 画像の編集終了
31.    painter.end()

```
-------
これをどこに実装するか?ラベルのこのイベントを乗っ取れば良いのかな
QWidget.paintEvent (self, QPaintEvent)

----
これで直接ウインドウに描画できるかもしれない
(ラベルにセットする意味がわからないので)
QPixmap.grabWidget (QWidget widget, QRect rect)

----



----
- コンテキストメニューを作るか
結構長くなるから別ファイルにしておくか??
このソフトの機能を呼び出すときの主要な手段になるよな

- コメント表示したい
exif のコメントとして現在は書き込んでいるので、他のソフトでも見れる
これを標準で見せるようにする
Qtでは取得出来なさそうだ
pillowなどのモジュールでイケそうだけど重そう
いずれ使うことになるのなら今から使ってもいいのだが
自作かな、コメントだけなら簡単そうだけど、書き込みは後でとりあえず読むだけなら
そもそもPixmap上にテキストを描画できるんだろうか?

- マウスジェスチャ 軌跡の表示
自作ものはジェスチャとコマンドが画像中心に表示される仕様だった
ウインドウを出してたんだな
別に無くても良いんだけど・・・・

- zip内の画像を順に表示できるようにする
一覧、スプレッドシートも必要
リストビューに画像表示させれば良いのかな
自作もののソースを見るか?
- 編集機能はどうしよう
回転は欲しいような気もするが
色調補正は別ソフトじゃ無きゃだめなような・・・
8bfをpythonから使えないかな???

# pillowについて調べた

画像のexif取得
とりあえず pillow 使ってみるか??

- インスト
https://qiita.com/agajo/items/90a29627e7c9a06ec24a
もしかしたら既にあるかも

- サイズはopenしたときに取得できるらしい
from PIL import Image
image = Image.open("shutterstock_450212698.jpg")
print("width: {}, height: {}".format(image.size[0], image.size[1]))

- エフェクトはここがわかりやすいね
Qtへの変換も
https://qiita.com/pashango2/items/145d858eff3c505c100a

- タグ取得はここ
https://qiita.com/Gen6/items/88c69ab3a0666895e7a8

- pil はQt変換を標準でサポートしてるのか??
https://dungeonneko.hatenablog.com/entry/2015/07/19/142034
Qpixmapに直接読み込むのとどっちが速いか試してみよう


# 画像への文字や矩形表示について調べた

- ここがすごくわかりやすいです
Python + PyQt5 画像の上に文字や矩形を上書き(drawText, drawRect, fillRect) 
https://symfoware.blog.fc2.com/blog-entry-2299.html
Qpixmapに直接でなく、一旦Qimageに読みこんでからQpixmapに読み込むみたい
時間かからないのかな?

- しかし画像に描画したいわけではない
画像の情報を表示する場所を画像の中にしたいだけ
単純にもう一つlabelを作って画像の上にかぶせて表示できないだろうか
これが出来れば各種の基本情報表示や、マウスジェスチャの表示も可能になる

- HTMLとしてラベルに表示するやり方があるようだ
http://blog.shibu.jp/article/60706676.html

- 画像表示した後単純に

**label.setText("Good Thing GOing") **
したらどうなるかな???


----
# コンテキストメニュー
考えたら右クリックにはジェスチャを設定していたから普通にコンテキストメニューを使うと反応してしまう

```
def mouseReleaseEvent(self,e)
 if self.ges['cmd'] == '' : # ジェスチャが無い場合はコンテキストメニューを出す
   c_menu.cmenu(e)
 else :
   元のコード
========================================
<< 本体ファイル >>

from PyQt5.QtCore import  Qt 
from custommenu.py import c_menu

__init__
 c_menu(self)
 self.label.setContextMenuPolicy(Qt.CustomContextMenu)
 self.label.customContextMenuRequested.connect(c_menu.cmenu)

label か mainwindow か???

<< 別ファイルで  custommenu.py >>

from PyQt5.QtWidgets import  QAction ,QMenu 


class c_menu():

 def __init__(self,p) :
  self.parent = p

 def c_menu(self,e): # e が来るのかな??
  menu=QMenu(self.parent)

  action = QAction('Open Folder', self.parent)
  action.triggered.connect(self.parent.**** )
  menu.addAction(action)

  action = QAction('AddToList', self.parent)
  action.triggered.connect(self.parent.**** )
  menu.addAction(action)

  # menu.exec_(QCursor.pos ())   
  menu.exec_( e )   
```
# EXIF 表示

https://qiita.com/Gen6/items/88c69ab3a0666895e7a8

from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS

def get_exif(file,field):

    img = Image.open(file)
    exif = img._getexif()

    exif_data = []
    for id, value in exif.items():
        if TAGS.get(id) == field:
            tag = TAGS.get(id, id),value
            exif_data.extend(tag)

    return exif_data

my_img = "sample.jpg"
print get_exif(my_img,"DateTimeOriginal")
===============わからん==========

```
# まずこれで実験してみよう

from PIL import Image
fname=r''
img = Image.open(file)
exif = img._getexif()

print('exif : ' , exif)
print('items : ' , exif.items() )
```

----
# zip内の画像を順に表示できるようにする

- 結構面倒だよ

とりあえずキーイベントで動作させよう

```
# self.pics=[]  これやめよう

def __init__
 self.current={'pics':[] , 'index':0, 'picslen':0 ,'zipflag':0 }
 self.zip={ 'pics':[] , 'index':0, 'picslen':0}
※このあとで self.pics は全て書き換えること(ここを含めて全8箇所)


def wheel の最後で
 showzip(1) # zip 初期化
 self.current['zipflag'] = 0  or 1

def keyPressEvent (self, e):
 if self.current['zipflag'] :
  if e.key()==Qt.Key_Down :
   self.calcnext( 'inc' )
  if e.key()==Qt.Key_Up :
   self.calcnext( 'dec' )
  showzip(0) # 既存    
  # zipでなければ無視



def showzip( self ,flag ):  # ここは書き換え
        zi = ZipFile( self.current['pics'][self.current['index'] ] , 'r' )
        if flag :
            self.zip['pics'].clear()
            self.zip['pics'] = zi.namelist()
            self.zip['picslen'] = len( self.zip['pics'] )
            self.zip['index'] = 0
        with zi.open( self.zip['pics'][ self.zip['index'] ] ) as z_image :
            pix = QPixmap()    # ここスワップした方が良いのかな
            pix.loadFromData(z_image.read())
            self.label.setPixmap(pix)
            self.resize(pix.width(),pix.height())
            self.show()
        zi.close()


<< サイクル計算するルーチン >>

def calcnext( sign ) :# 増か減か
 if self.current['zipflag'}:
  index = self.zip['index']
  len = self.zip['picslen']
 else:
  index = self.current['index']
  len = self.current['picslen']

 if sign == 'inc':
  index += 1
  if index > (len-1) :
   index=0
 elif sign == 'dec' :
  index -= 1
  if index < 0:
   index = len-1

 if self.current['zipflag'}:
  self.zip['index'] = index
 else:
  self.current['index'] = index
```
- 三項演算子
x = "OK" if n == 10 else "NG"

こうやって書けるのかな?

 if sign == 'inc':
  index = index+1  if index < len-1  else  0
 elif sign == 'dec' :
  index = index-1  if index => 0  else  len-1

----

[目次に戻る](https://mimemo.io/m/QORbW4qkvOoda0N)
      

項目pillowについて調べた画像への文字や矩形表示について調べたコンテキストメニューEXIF 表示zip内の画像を順に表示できるようにする

  • まずテキスト表示を試してみる
    ①単純に現在のlabelにsettextしてみる
    ②ダメならlabelにlabelを子供としてセットしてみる
    addwidget ?
    label=QLabel(label) でいけないかな?

  • ↑ 190620にやってみたけどダメだった┐('д')┌
    ①は画像が消えて文字だけになってしまいます
    ②は何も変わりません
    QLabelは子供を持つことが出来ないのか??

あくまでwifgetを配置
 labelの子供じゃ無くてmainwindowに直接配置するか?
 レイアウトを解除するか?
QPainterで上書き
 DCを取得して書き込んでしまう

ラベルのペイントイベント
QWidget.paintEvent (self, QPaintEvent)

label.paintEvent()

ペインターを動かすにはデバイスが必要
QPainter.init (self, QPaintDevice)
QPixmapはデバイスの承継だからこれに直接書ける


QPainter Class Reference [QtGui module]

dc=QPainter( pixmap )
dc.begin()
dc.drawText( 0,0, 'hogetta' )
dc.end()

  • 参考
    # ペンの色を指定
23.    painter.setPen(Qt.red)
24.    #painter.setPen(QColor(255, 0, 0))
25.    
26.    # 使用するフォントを指定
27.    painter.setFont(QFont('Times', 30))
28.    # テキスト描画
29.    painter.drawText(image.rect(), Qt.AlignCenter, 'Symfoware')
30.    # 画像の編集終了
31.    painter.end()


これをどこに実装するか?ラベルのこのイベントを乗っ取れば良いのかな
QWidget.paintEvent (self, QPaintEvent)


これで直接ウインドウに描画できるかもしれない
(ラベルにセットする意味がわからないので)
QPixmap.grabWidget (QWidget widget, QRect rect)



  • コンテキストメニューを作るか
    結構長くなるから別ファイルにしておくか??
    このソフトの機能を呼び出すときの主要な手段になるよな

  • コメント表示したい
    exif のコメントとして現在は書き込んでいるので、他のソフトでも見れる
    これを標準で見せるようにする
    Qtでは取得出来なさそうだ
    pillowなどのモジュールでイケそうだけど重そう
    いずれ使うことになるのなら今から使ってもいいのだが
    自作かな、コメントだけなら簡単そうだけど、書き込みは後でとりあえず読むだけなら
    そもそもPixmap上にテキストを描画できるんだろうか?

  • マウスジェスチャ 軌跡の表示
    自作ものはジェスチャとコマンドが画像中心に表示される仕様だった
    ウインドウを出してたんだな
    別に無くても良いんだけど・・・・

  • zip内の画像を順に表示できるようにする
    一覧、スプレッドシートも必要
    リストビューに画像表示させれば良いのかな
    自作もののソースを見るか?

  • 編集機能はどうしよう
    回転は欲しいような気もするが
    色調補正は別ソフトじゃ無きゃだめなような・・・
    8bfをpythonから使えないかな???

pillowについて調べた

画像のexif取得
とりあえず pillow 使ってみるか??

画像への文字や矩形表示について調べた

  • ここがすごくわかりやすいです
    Python + PyQt5 画像の上に文字や矩形を上書き(drawText, drawRect, fillRect)
    https://symfoware.blog.fc2.com/blog-entry-2299.html
    Qpixmapに直接でなく、一旦Qimageに読みこんでからQpixmapに読み込むみたい
    時間かからないのかな?

  • しかし画像に描画したいわけではない
    画像の情報を表示する場所を画像の中にしたいだけ
    単純にもう一つlabelを作って画像の上にかぶせて表示できないだろうか
    これが出来れば各種の基本情報表示や、マウスジェスチャの表示も可能になる

  • HTMLとしてラベルに表示するやり方があるようだ
    http://blog.shibu.jp/article/60706676.html

  • 画像表示した後単純に

**label.setText("Good Thing GOing") **
したらどうなるかな???


コンテキストメニュー

考えたら右クリックにはジェスチャを設定していたから普通にコンテキストメニューを使うと反応してしまう

def mouseReleaseEvent(self,e)
 if self.ges['cmd'] == '' : # ジェスチャが無い場合はコンテキストメニューを出す
   c_menu.cmenu(e)
 else :
   元のコード
========================================
<< 本体ファイル >>

from PyQt5.QtCore import  Qt 
from custommenu.py import c_menu

__init__
 c_menu(self)
 self.label.setContextMenuPolicy(Qt.CustomContextMenu)
 self.label.customContextMenuRequested.connect(c_menu.cmenu)

label か mainwindow か???

<< 別ファイルで  custommenu.py >>

from PyQt5.QtWidgets import  QAction ,QMenu 


class c_menu():

 def __init__(self,p) :
  self.parent = p

 def c_menu(self,e): # e が来るのかな??
  menu=QMenu(self.parent)

  action = QAction('Open Folder', self.parent)
  action.triggered.connect(self.parent.**** )
  menu.addAction(action)

  action = QAction('AddToList', self.parent)
  action.triggered.connect(self.parent.**** )
  menu.addAction(action)

  # menu.exec_(QCursor.pos ())   
  menu.exec_( e )   

EXIF 表示

https://qiita.com/Gen6/items/88c69ab3a0666895e7a8

from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS

def get_exif(file,field):

img = Image.open(file)
exif = img._getexif()

exif_data = []
for id, value in exif.items():
    if TAGS.get(id) == field:
        tag = TAGS.get(id, id),value
        exif_data.extend(tag)

return exif_data

my_img = "sample.jpg"
print get_exif(my_img,"DateTimeOriginal")
===============わからん==========

# まずこれで実験してみよう

from PIL import Image
fname=r''
img = Image.open(file)
exif = img._getexif()

print('exif : ' , exif)
print('items : ' , exif.items() )

zip内の画像を順に表示できるようにする

  • 結構面倒だよ

とりあえずキーイベントで動作させよう

# self.pics=[]  これやめよう

def __init__
 self.current={'pics':[] , 'index':0, 'picslen':0 ,'zipflag':0 }
 self.zip={ 'pics':[] , 'index':0, 'picslen':0}
※このあとで self.pics は全て書き換えること(ここを含めて全8箇所)


def wheel の最後で
 showzip(1) # zip 初期化
 self.current['zipflag'] = 0  or 1

def keyPressEvent (self, e):
 if self.current['zipflag'] :
  if e.key()==Qt.Key_Down :
   self.calcnext( 'inc' )
  if e.key()==Qt.Key_Up :
   self.calcnext( 'dec' )
  showzip(0) # 既存    
  # zipでなければ無視



def showzip( self ,flag ):  # ここは書き換え
        zi = ZipFile( self.current['pics'][self.current['index'] ] , 'r' )
        if flag :
            self.zip['pics'].clear()
            self.zip['pics'] = zi.namelist()
            self.zip['picslen'] = len( self.zip['pics'] )
            self.zip['index'] = 0
        with zi.open( self.zip['pics'][ self.zip['index'] ] ) as z_image :
            pix = QPixmap()    # ここスワップした方が良いのかな
            pix.loadFromData(z_image.read())
            self.label.setPixmap(pix)
            self.resize(pix.width(),pix.height())
            self.show()
        zi.close()


<< サイクル計算するルーチン >>

def calcnext( sign ) :# 増か減か
 if self.current['zipflag'}:
  index = self.zip['index']
  len = self.zip['picslen']
 else:
  index = self.current['index']
  len = self.current['picslen']

 if sign == 'inc':
  index += 1
  if index > (len-1) :
   index=0
 elif sign == 'dec' :
  index -= 1
  if index < 0:
   index = len-1

 if self.current['zipflag'}:
  self.zip['index'] = index
 else:
  self.current['index'] = index
  • 三項演算子
    x = "OK" if n == 10 else "NG"

こうやって書けるのかな?

if sign == 'inc':
index = index+1 if index < len-1 else 0
elif sign == 'dec' :
index = index-1 if index => 0 else len-1


目次に戻る