質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1330閲覧

KivyのScrollViewで中クリックによるドラッグでスクロールさせたい

brsice

総合スコア17

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/06/06 14:20

編集2018/06/06 14:21

前提・実現したいこと

KivyのScrollViewの内部で、左クリックによるドラッグ操作を使いたいため、中クリック(ホイールクリック)によるドラッグでスクロールさせたいと思っています。
右クリックで赤い丸が出ないように、
Config.set('input', 'mouse', 'mouse,disable_multitouch')
でマルチタッチを無効にしたのですが、右クリック、中クリックともに左クリックと同様に扱われてしまいスクロールには使えません。
中クリックは左クリックとは扱わず、スクロール用として使えるようにしたいです。

簡単なScrollViewのコードを載せておきます。

該当のソースコード

Python

1from kivy.config import Config 2Config.set("graphics", "width", 600) 3Config.set("graphics", "height", 600) 4Config.set('input', 'mouse', 'mouse,disable_multitouch') 5 6from kivy.app import App 7 8 9class TestApp(App): 10 pass 11 12if __name__ == '__main__': 13 TestApp().run()

test.kv

FloatLayout: ScrollView: scroll_type: ['bars', 'content'] size_hint: None, None size: root.size GridLayout: rows:2 cols:2 size_hint: None, None size: 1000,1000 Widget: canvas: Color: rgb: 1, 0, 0 Rectangle size: self.size pos: self.pos Widget: canvas: Color: rgb: 0, 0, 1 Rectangle size: self.size pos: self.pos Widget: canvas: Color: rgb: 0, 1, 0 Rectangle size: self.size pos: self.pos Widget: canvas: Color: rgb: 1, 1, 1 Rectangle size: self.size pos: self.pos

補足情報(FW/ツールのバージョンなど)

Python: v3.6.5
Kivy: v1.10.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

コメントだとMarkdown使えないのでこっちに書きますね。

このコードでは確かにそう捉えられてしまいますね、すみません、説明不足でした。

右クリック・中クリックでも問題なくスクロールできております。

あっ今わかりました。右クリック・中クリックでもボタンが反応してしまうのが困るという意味だったんですよね多分。

KivyにおいてMouseのような画面上の位置を指す類の入力はWidgetTreeの親から子へ順番に伝わっていくので、ボタンの祖先(直接の親とそのさらに上の親達)のWidgetのどれかを右クリック・中クリックを子に伝えないようにすればいいです。ただScrollViewでは中クリックを使いたいはずなので、ScrollViewの子孫でなおかつボタンの祖先であるWidget(上のコードでいうならGridLayout)にそのような仕事をさせてあげればいいです。

具体的には例えば以下のような入力を選別するClassを作って

python

1from kivy.factory import Factory 2from kivy.properties import ListProperty 3 4# 入力を選別するClass 5class TouchFilter: 6 mouse_button_filter = ListProperty() 7 8 def on_touch_down(self, touch): 9 if touch.button in self.mouse_button_filter: 10 return super().on_touch_down(touch) 11 12 def on_touch_move(self, touch): 13 if touch.button in self.mouse_button_filter: 14 return super().on_touch_move(touch) 15 16 def on_touch_up(self, touch): 17 if touch.button in self.mouse_button_filter: 18 return super().on_touch_up(touch) 19 20 21# TouchFilterをKv言語でも使えるようにする 22Factory.register('TouchFilter', cls=TouchFilter)

それを組み込んだGridLayoutを作って、元のGridLayoutと置き換えることで実現できます。

<CustomGridLayout@TouchFilter+GridLayout>: # TouchFilterを組み込んだGridLayout FloatLayout: ScrollView: 略 CustomGridLayout: # 元のGridLayoutを置き換える mouse_button_filter: ['left', ] # 子には左ボタンの入力しか伝わらなくする 略

左ドラッグを使いたいという件ですが、ソースコードは載せられないのですが、大まかには「ボタンがたくさん並んでいて、それをドラッグでなぞっただけで動作させたい」という認識で大丈夫です。

on_pressだと難しそうなので、on_touch_downとon_touch_move内でcollide_pointを使って実現しています。

なるほど、わかりました。kivy.uix.button.Buttonを使うか否かは悩むところですね。Buttonの持つ機能の内stateプロパティは役に立ちそうですが、touchに関する処理は全て自前で実装することになりそうなので。

投稿2018/06/11 04:13

gottadiveintopy

総合スコア736

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gottadiveintopy

2018/06/11 15:46

今思ったのですが、別に > 右クリック・中クリックでもボタンが反応してしまうのが困るという意味 ではなかったですね。一応上記のコードのようにする事で中クリックや右クリックではボタンをなぞれなくなるので、参考までに。
brsice

2018/06/13 10:06

「クリックの種類によってscroll_typeを変更するScrollViewの派生class」の中に、「クリックを選別するclassを継承したGridLayout」を配置することで、スクロールは左クリック以外、ボタンは左クリックのみの動作を実現することができました。 ありがとうございます。 プログラミング自体初心者ですが、GUIで何かを作るのは初めてなので、入力も継承されるというのは考え至りませんでした、勉強になります。 とりあえずScrollVeiwの問題を先に解決したかっただけで、GridLayout内での右クリック・中クリックをどうするかというのも後々考える必要があったので助かりました。 Buttonに関しては私も使う意味が薄いと考えており、Widgetにcanvasで色付けしたものを使用しているのですが、何か他に適したものはあるでしょうか? Widgetの数は1000個以上に増やすこともあるので、少しでも適したものをと思っています。 大きなWidgetを作成して内部でどこをクリックしたか判断する形にした方が軽くなるのかなとは思っているのですが・・・。
gottadiveintopy

2018/06/19 02:18 編集

> 入力も継承されるというのは考え至りませんでした いえ、私が言いたかったのは親Widgetが子Widget達のon_touch_xxx()を再帰的に呼ぶ事で入力が伝わっていくという事です。下のリンクは全てのWidgetの基底Classであるkivy.uix.widget.Widgetのon_touch_xxx()の実装なんですが、そうなっているのが分かると思います。 https://github.com/kivy/kivy/blob/master/kivy/uix/widget.py#L443-L483 > 何か他に適したものはあるでしょうか? その方法で問題ないかと思います。 > 1000以上の それだけの数になるのならRecycleViewが適切かと。
brsice

2018/06/22 06:05

わざわざ仕組みまで教えていただいてありがとうございます。 困ったら付近の実装を確かめるのも大事そうですね。 RecycleViewに関しては使い方もどのように表示されるのかも全く知らないので、時間がある時に試してみようと思います。
guest

0

でマルチタッチを無効にしたのですが、右クリック、中クリックともに左クリックと同様に扱われてしまいスクロールには使えません。

マルチタッチはあくまで複数のタッチを実現するだけで、個々のボタンの役割が変わったりしないはずです。なので無効にしようがしまいが右クリック・中クリックでスクロールできるはずなのですが(実際私の環境ではできています)、主さんの環境でできていないのは確かですか?

あとマウスの入力をScrollViewの内部でどのように扱いたいか、細かく以下の7つ

  • 左クリック
  • 右クリック
  • 中クリック
  • 左ドラッグ
  • 右ドラッグ
  • 中ドラッグ
  • ホイールを回す

について分かりますか?

投稿2018/06/10 10:31

gottadiveintopy

総合スコア736

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

brsice

2018/06/10 10:49

このコードでは確かにそう捉えられてしまいますね、すみません、説明不足でした。 右クリック・中クリックでも問題なくスクロールできております。 上のサンプルコードはScrollViewについて試行錯誤するために作成したもので、仮にscroll_type: ['bars', 'content']としていますが、私が求める挙動は以下のようなものです。 ・左クリック・左ドラッグでは'bars'の動作 ・中クリック・中ドラッグでは'content'の動作  あるいはオートスクロールのような動作でも可 ・ホイール操作は通常のスクロール 左ドラッグはon_touch_moveで使用しているため、スクロールには使いたくないのです。 右クリックについては特に使用予定はないので、左クリック同様の動作でも使用不可でも構いません。
gottadiveintopy

2018/06/10 12:24 編集

> 左クリック・左ドラッグでは'bars'の動作 > 中クリック・中ドラッグでは'content'の動作 これはScrollViewの派生Classを作って、on_touch_down()を上書きする方法しか思いつかないですね。 on_touch_down()の仮引数touchのbutton属性を見て、ScrollViewのscroll_typeプロパティを変更してあげればできると思います。 > 右クリックについては特に使用予定はないので、左クリック同様の動作でも使用不可でも構いません。 使用不可にしたいなら上の派生Classを使った方法か、ScrollViewの親Widgetとして右ボタン入力を伝搬しないWidgetを作って用意してあげればできそうです。追記:もしアプリ全体に渡って右ボタンが要らないのなら、rootのWidgetを右ボタン入力を伝搬しないようにしてしまえばいいと思います。因みに右ボタン入力の伝搬を止めるには以下のようなメソッドを書いてあげればできます。 def on_touch_down(self, touch): ____if touch.button != 'right': ________return super().on_touch_down(touch) > 左ドラッグはon_touch_moveで使用しているため、スクロールには使いたくないのです。 これがよくわからないのですが、ソースコードは載せられますか?
brsice

2018/06/10 20:28

>> 左クリック・左ドラッグでは'bars'の動作 >> 中クリック・中ドラッグでは'content'の動作 > >これはScrollViewの派生Classを作って、on_touch_down()を上書きする方法しか思いつかないですね。 >on_touch_down()の仮引数touchのbutton属性を見て、ScrollViewのscroll_typeプロパティを変更してあげればできると思います。 ありがとうございます。 今すぐに試せないのですが、その方法で思ったとおりの動作にできそうです。 恥ずかしながらクリックの種類を見分ける方法をリファレンスから見つけられなかったもので、下に書いていただいているコードで歯がゆかったところに手が届きそうです。 左ドラッグを使いたいという件ですが、ソースコードは載せられないのですが、大まかには「ボタンがたくさん並んでいて、それをドラッグでなぞっただけで動作させたい」という認識で大丈夫です。 on_pressだと難しそうなので、on_touch_downとon_touch_move内でcollide_pointを使って実現しています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問