複数の画像を読み込んで、フォームの背景画像を動的に変更する方法を教えて下さい。
投稿者 るきお  (社会人)
投稿日時
2020/10/16 08:12:01
>実行すると、「System.ArgumentException: '使用されたパラメーターが有効ではありません。'」
がでます。
どの行でそれが出ますか?
何が起こっているのかよくわからないので、
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
の行を
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Shown
に変更して実行してみて、エラーが変わるかどうかご確認ください。
※Loadイベント内で発生したエラーをVisual Studioは報告してくれない非常に特殊なイベントなので、VB+VC# Beginner さんが気が付いていない別のエラーが実は発生しているかもしれません。Shownイベントはフォームが表示されたタイミングで発生し、この中のエラーであればVisual Studioは報告してくれます。
>コードエディターで Dim img(9) ~ Dim jpgFiles の行にIDE0044 Visual Basic Make field readonlyが出ています。
これはVisual Studioからのアドバイスですが、今回のエラーには関係ないです。
変数imgと変数dirは初期値を設定する以外、後で値を変更していないので、Reaonlyキーワードを使って読み取り専用にしてみてはどうでしょう? というVisual Studioからの控えめな提案です。無視しでも機能・性能に影響はありません。
ところで、VB+VC# Beginner さんが、今のプログラムに興味がなく、やりたいこと①と③が実現できる方法がわかれば何でも良いということでしたら、簡単なサンプルを紹介することもできますよ。
私は、②について、画像をあらかじめ読み込んでおくのはメモリーがもったいないので好きではないのですが、Timerの間隔を非常に短くしてアニメーションのような効果を期待しているのであれば、確かに重要ですね。
がでます。
どの行でそれが出ますか?
何が起こっているのかよくわからないので、
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
の行を
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Shown
に変更して実行してみて、エラーが変わるかどうかご確認ください。
※Loadイベント内で発生したエラーをVisual Studioは報告してくれない非常に特殊なイベントなので、VB+VC# Beginner さんが気が付いていない別のエラーが実は発生しているかもしれません。Shownイベントはフォームが表示されたタイミングで発生し、この中のエラーであればVisual Studioは報告してくれます。
>コードエディターで Dim img(9) ~ Dim jpgFiles の行にIDE0044 Visual Basic Make field readonlyが出ています。
これはVisual Studioからのアドバイスですが、今回のエラーには関係ないです。
変数imgと変数dirは初期値を設定する以外、後で値を変更していないので、Reaonlyキーワードを使って読み取り専用にしてみてはどうでしょう? というVisual Studioからの控えめな提案です。無視しでも機能・性能に影響はありません。
ところで、VB+VC# Beginner さんが、今のプログラムに興味がなく、やりたいこと①と③が実現できる方法がわかれば何でも良いということでしたら、簡単なサンプルを紹介することもできますよ。
私は、②について、画像をあらかじめ読み込んでおくのはメモリーがもったいないので好きではないのですが、Timerの間隔を非常に短くしてアニメーションのような効果を期待しているのであれば、確かに重要ですね。
投稿者 VB+VC# Beginner  (社会人)
投稿日時
2020/10/16 19:06:07
るきお様
ご回答ありがとうございました。
ご指摘の通り、
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
⇒
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Shown
に変更しても、表示内容は一緒でした。
前回記述していませんでしたが、前述のエラー以外に、
「アプリケーションはブレークモードになっています」(大きな字)
「お使いのアプリはブレーク状態になりましたが、すべてのスレッドが外部コード (通常はシステム コードまたはフレームワーク コード) を
実行していたため、表示されるコードはありません。」(細かい字)
も出ていました。
画像の切り替えは、テスト段階では、1~5秒程度、最終的には1~10分に一度になる予定です。
画像は取り敢えず10個でテストしますが、画像が集まれば30~60個程度を予定しています。
メモリーに入れておけば切り替えがスムーズであるとどこかで読みましたが、ご指摘の通り、メモリーの無駄遣いになるのなら
今後検討するとして、まずは動作確認をしたいので、①+③のサンプルを紹介して下さい。
お手数をおかけしますが、宜しくお願い致します。
ご回答ありがとうございました。
ご指摘の通り、
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
⇒
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Shown
に変更しても、表示内容は一緒でした。
前回記述していませんでしたが、前述のエラー以外に、
「アプリケーションはブレークモードになっています」(大きな字)
「お使いのアプリはブレーク状態になりましたが、すべてのスレッドが外部コード (通常はシステム コードまたはフレームワーク コード) を
実行していたため、表示されるコードはありません。」(細かい字)
も出ていました。
画像の切り替えは、テスト段階では、1~5秒程度、最終的には1~10分に一度になる予定です。
画像は取り敢えず10個でテストしますが、画像が集まれば30~60個程度を予定しています。
メモリーに入れておけば切り替えがスムーズであるとどこかで読みましたが、ご指摘の通り、メモリーの無駄遣いになるのなら
今後検討するとして、まずは動作確認をしたいので、①+③のサンプルを紹介して下さい。
お手数をおかけしますが、宜しくお願い致します。
投稿者 るきお  (社会人)
投稿日時
2020/10/16 20:44:16
>前回記述していませんでしたが、前述のエラー以外に、
>「アプリケーションはブレークモードになっています」(大きな字)
>「お使いのアプリはブレーク状態になりましたが、すべてのスレッドが外部コード (通常はシステム コードまたはフレームワーク コード) を
>実行していたため、表示されるコードはありません。」(細かい字)
>も出ていました。
いろいろ妙なので、プログラムの問題以外に、実行環境の状態や設定がおかしいのかもしれません。
[ツール]メニューの[設定のインポートとエクスポート]を使うと、すべての設定を最初の状態に戻すことができます。
また、原因が追求できないのならば、現在のプログラムはもう開かないことにして、新しいプロジェクトを作成しなすと良いかもしれません。
フォルダー内の画像(jpg)を次々と切り替えるサンプルを紹介します。
私の環境では動作します。
このサンプルではマイピクチャーフォルダーを対象にしていますが、下記のようにimageFolderの値を変更することで任意のフォルダーを対象にすることができます。
Dim imageFolder As String = "C:\xxxx\ddddd"
すべての画像を最初の段階でメモリー上に読み込んでおく例も紹介します。
いろいろな書き方があり、上記はほんの一例です。
>「アプリケーションはブレークモードになっています」(大きな字)
>「お使いのアプリはブレーク状態になりましたが、すべてのスレッドが外部コード (通常はシステム コードまたはフレームワーク コード) を
>実行していたため、表示されるコードはありません。」(細かい字)
>も出ていました。
いろいろ妙なので、プログラムの問題以外に、実行環境の状態や設定がおかしいのかもしれません。
[ツール]メニューの[設定のインポートとエクスポート]を使うと、すべての設定を最初の状態に戻すことができます。
また、原因が追求できないのならば、現在のプログラムはもう開かないことにして、新しいプロジェクトを作成しなすと良いかもしれません。
フォルダー内の画像(jpg)を次々と切り替えるサンプルを紹介します。
私の環境では動作します。
Public Class Form1
Dim filePointer As IEnumerator(Of String)
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
'▼マイピクチャーフォルダーの直下にある 拡張子が jpg のファイルのパスの一覧を取得します。
Dim imageFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
Dim fileNames As New List(Of String)(IO.Directory.GetFiles(imageFolder, "*.jpg"))
'▼一覧の画像を指し示すポインター(列挙子)を取得して、最初の画像を表示します。
filePointer = fileNames.GetEnumerator()
ShowNextImage()
'タイマー起動。以降は 3秒ごとに次の画像を表示します。
Timer1.Interval = 3000
Timer1.Enabled = True
End Sub
''' <summary>
''' filePointerの次の画像を表示します。次の画像がない場合、最初の画像を表示します。
''' ファイルが1つもない場合はエラーになります。
''' </summary>
Private Sub ShowNextImage()
If filePointer.MoveNext = False Then
filePointer.Reset()
filePointer.MoveNext()
End If
Me.BackgroundImage = Image.FromFile(filePointer.Current)
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
ShowNextImage()
End Sub
End Class
このサンプルではマイピクチャーフォルダーを対象にしていますが、下記のようにimageFolderの値を変更することで任意のフォルダーを対象にすることができます。
Dim imageFolder As String = "C:\xxxx\ddddd"
すべての画像を最初の段階でメモリー上に読み込んでおく例も紹介します。
Public Class Form1
Dim filePointer As IEnumerator(Of Image)
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
'▼マイピクチャーフォルダーの直下にある 拡張子が jpg のファイルの画像の一覧を取得します。
Dim imageFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
Dim images As New List(Of Image)
For Each fileName As String In IO.Directory.GetFiles(imageFolder, "*.jpg")
images.Add(Image.FromFile(fileName))
Next
'▼一覧の画像を指し示すポインター(列挙子)を取得して、最初の画像を表示します。
filePointer = images.GetEnumerator()
ShowNextImage()
'タイマー起動。以降は 3秒ごとに次の画像を表示します。
Timer1.Interval = 3000
Timer1.Enabled = True
End Sub
''' <summary>
''' filePointerの次の画像を表示します。次の画像がない場合、最初の画像を表示します。
''' ファイルが1つもない場合はエラーになります。
''' </summary>
Private Sub ShowNextImage()
If filePointer.MoveNext = False Then
filePointer.Reset()
filePointer.MoveNext()
End If
Me.BackgroundImage = filePointer.Current
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
ShowNextImage()
End Sub
End Class
いろいろな書き方があり、上記はほんの一例です。
投稿者 VB+VC# Beginner  (社会人)
投稿日時
2020/10/17 19:25:03
るきお様
昨日は投稿後すぐに外出し、
先ほど仕事から帰宅し、今読み終わったところです。
ありがとうございました。
試してみます。
昨日は投稿後すぐに外出し、
先ほど仕事から帰宅し、今読み終わったところです。
ありがとうございました。
試してみます。
投稿者 VB+VC# Beginner  (社会人)
投稿日時
2020/10/17 23:50:42
るきお様
① Dim filePointer As IEnumerator(Of String)
② Dim filePointer As IEnumerator(Of Image)
の両方とも、私のパソコン環境でも正しく背景画像を変更できました。
①と②では、プロセスメモリーのグラフに歴然とした差が見られました。
3秒ごとの変更では、①でもスムーズに切り替わりましたので、
あえてイメージを読み込んでおく必要はなさそうですね。
私が画像を変更したいプロジェクトには、すでに Timer は Interval = 1000 で
使用していますので、xx秒ごとに ShowNextImage() を呼び出すことは可能です。
フォルダー内のファイル数のカウントの仕方はネットで調べられましたので、
エラーは防げそうです。
(画像を変更したいので、あえてファイルを消すことはありませんが。)
どうもありがとうございました。
① Dim filePointer As IEnumerator(Of String)
② Dim filePointer As IEnumerator(Of Image)
の両方とも、私のパソコン環境でも正しく背景画像を変更できました。
①と②では、プロセスメモリーのグラフに歴然とした差が見られました。
3秒ごとの変更では、①でもスムーズに切り替わりましたので、
あえてイメージを読み込んでおく必要はなさそうですね。
私が画像を変更したいプロジェクトには、すでに Timer は Interval = 1000 で
使用していますので、xx秒ごとに ShowNextImage() を呼び出すことは可能です。
フォルダー内のファイル数のカウントの仕方はネットで調べられましたので、
エラーは防げそうです。
(画像を変更したいので、あえてファイルを消すことはありませんが。)
どうもありがとうございました。
やりたいことは、
① 1つのフォルダーに、0.jpg ~ 9.jpg を用意しました。
② 画像をあらかじめ、img(0) ~ img(9) に読み込みたい。
③ タイマーでフォームの背景画を変更したい。
ネットで、以下のコードを見つけましたが、全く理解できず、見よう見まねで
変更しましたが、開始後数秒でエラーになります。
参考ページ :
https://www.atmarkit.co.jp/fdotnet/dotnettips/597fastloadimg/fastloadimg.html
Imports System.IO
Public Class Form1
Dim i As Integer
Dim img(9) As Image
Dim dir As String = "E:\My Documents\My Picture\..."
Dim jpgFiles As String() = Directory.GetFiles(dir, "*.jpg")
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
i = 0
For Each jpg As String In jpgFiles
Using fs As FileStream = File.OpenRead(jpg)
Using image As Image = Image.FromStream(fs, False, False)
img(i) = image
i += 1
End Using
End Using
Next
i = 0
Timer1.Enabled = True
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If i < img.Length - 1 Then
i += 1
Else
i = 0
End If
Me.BackgroundImage = img(i)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Application.Exit()
End Sub
End Class
コードエディターで Dim img(9) ~ Dim jpgFiles の行に
IDE0044 Visual Basic Make field readonly
が出ています。
実行すると、「System.ArgumentException: '使用されたパラメーターが有効ではありません。'」
がでます。
他のページも検索しましたが、見つからなかったので質問します。
宜しくお願い致します。